about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/hatchet_sdk/clients
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/hatchet_sdk/clients')
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/admin.py542
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/dispatcher/action_listener.py423
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/dispatcher/dispatcher.py204
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/event_ts.py28
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/events.py183
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/__init__.py293
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/__init__.py19
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/api_token_api.py858
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/default_api.py2257
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/event_api.py2548
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/github_api.py331
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/healthcheck_api.py483
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/log_api.py447
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/metadata_api.py728
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/rate_limits_api.py423
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/slack_api.py577
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/sns_api.py872
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/step_run_api.py2200
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/tenant_api.py4428
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/user_api.py2888
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/worker_api.py858
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/workflow_api.py6310
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/workflow_run_api.py1932
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/workflow_runs_api.py610
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api_client.py759
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api_response.py22
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/configuration.py611
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/exceptions.py200
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/__init__.py260
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/accept_invite_request.py83
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_error.py102
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_errors.py100
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_meta.py144
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_meta_auth.py85
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_meta_integration.py88
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_meta_posthog.py90
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_resource_meta.py98
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_token.py105
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/bulk_create_event_request.py100
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/bulk_create_event_response.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cancel_event_request.py85
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cancel_step_run_request.py83
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/concurrency_limit_strategy.py39
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_api_token_request.py92
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_api_token_response.py83
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_cron_workflow_trigger_request.py98
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_event_request.py95
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_pull_request_from_step_run.py83
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_sns_integration_request.py85
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_tenant_alert_email_group_request.py83
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_tenant_invite_request.py86
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_tenant_request.py84
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cron_workflows.py131
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cron_workflows_list.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cron_workflows_method.py37
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cron_workflows_order_by_field.py37
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event.py143
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_data.py83
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_key_list.py98
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_list.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_order_by_direction.py37
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_order_by_field.py36
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_update_cancel200_response.py85
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_workflow_run_summary.py116
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/events.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/get_step_run_diff_response.py100
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/github_app_installation.py107
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/github_branch.py86
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/github_repo.py86
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/info_get_version200_response.py83
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/job.py132
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/job_run.py176
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/job_run_status.py41
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/link_github_repository_request.py106
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_api_tokens_response.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_github_app_installations_response.py112
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_pull_requests_response.py100
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_slack_webhooks.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_sns_integrations.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line.py94
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line_level.py39
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line_list.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line_order_by_direction.py37
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line_order_by_field.py36
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/pagination_response.py95
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/pull_request.py112
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/pull_request_state.py37
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/queue_metrics.py97
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rate_limit.py117
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rate_limit_list.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rate_limit_order_by_direction.py37
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rate_limit_order_by_field.py38
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/recent_step_runs.py118
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/reject_invite_request.py83
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/replay_event_request.py85
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/replay_workflow_runs_request.py85
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/replay_workflow_runs_response.py100
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rerun_step_run_request.py83
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/schedule_workflow_run_request.py92
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_run_status.py42
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_workflows.py149
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_workflows_list.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_workflows_method.py37
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_workflows_order_by_field.py37
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/semaphore_slots.py113
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/slack_webhook.py127
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/sns_integration.py114
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step.py123
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run.py202
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_archive.py142
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_archive_list.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_diff.py91
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_event.py120
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_event_list.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_event_reason.py52
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_event_severity.py38
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_status.py44
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant.py118
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_alert_email_group.py98
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_alert_email_group_list.py112
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_alerting_settings.py143
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_invite.py120
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_invite_list.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_list.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_member.py123
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_member_list.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_member_role.py38
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_queue_metrics.py116
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_resource.py40
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_resource_limit.py135
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_resource_policy.py102
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_step_run_queue_metrics.py83
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/trigger_workflow_run_request.py91
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/update_tenant_alert_email_group_request.py83
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/update_tenant_invite_request.py85
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/update_tenant_request.py137
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/update_worker_request.py87
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user.py126
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_change_password_request.py88
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_login_request.py86
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_register_request.py91
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_tenant_memberships_list.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_tenant_public.py86
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker.py100
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_create_request.py94
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_create_response.py96
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_created.py102
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_list_response.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_request.py102
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_request_list_response.py102
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_request_method.py38
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker.py239
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_label.py102
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_list.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_runtime_info.py103
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_runtime_sdks.py38
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_type.py38
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow.py165
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_concurrency.py107
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_deployment_config.py136
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_kind.py38
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_list.py120
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_metrics.py97
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run.py188
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_cancel200_response.py85
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_list.py110
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_order_by_direction.py37
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_order_by_field.py39
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_shape.py186
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_status.py42
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_triggered_by.py112
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_runs_cancel_request.py85
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_runs_metrics.py94
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_runs_metrics_counts.py104
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_tag.py84
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_trigger_cron_ref.py86
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_trigger_event_ref.py86
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_triggers.py141
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_update_request.py85
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_version.py170
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_version_concurrency.py114
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_version_definition.py85
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_version_meta.py123
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_workers_count.py95
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/rest.py187
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/tenacity_utils.py39
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest_client.py611
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/run_event_listener.py260
-rw-r--r--.venv/lib/python3.12/site-packages/hatchet_sdk/clients/workflow_listener.py277
189 files changed, 48543 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/admin.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/admin.py
new file mode 100644
index 00000000..18664cef
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/admin.py
@@ -0,0 +1,542 @@
+import json
+from datetime import datetime
+from typing import Any, Callable, Dict, List, Optional, TypedDict, TypeVar, Union
+
+import grpc
+from google.protobuf import timestamp_pb2
+
+from hatchet_sdk.clients.rest.models.workflow_run import WorkflowRun
+from hatchet_sdk.clients.rest.tenacity_utils import tenacity_retry
+from hatchet_sdk.clients.run_event_listener import new_listener
+from hatchet_sdk.clients.workflow_listener import PooledWorkflowRunListener
+from hatchet_sdk.connection import new_conn
+from hatchet_sdk.contracts.workflows_pb2 import (
+    BulkTriggerWorkflowRequest,
+    BulkTriggerWorkflowResponse,
+    CreateWorkflowVersionOpts,
+    PutRateLimitRequest,
+    PutWorkflowRequest,
+    RateLimitDuration,
+    ScheduleWorkflowRequest,
+    TriggerWorkflowRequest,
+    TriggerWorkflowResponse,
+    WorkflowVersion,
+)
+from hatchet_sdk.contracts.workflows_pb2_grpc import WorkflowServiceStub
+from hatchet_sdk.utils.serialization import flatten
+from hatchet_sdk.workflow_run import RunRef, WorkflowRunRef
+
+from ..loader import ClientConfig
+from ..metadata import get_metadata
+from ..workflow import WorkflowMeta
+
+
+def new_admin(config: ClientConfig):
+    return AdminClient(config)
+
+
+class ScheduleTriggerWorkflowOptions(TypedDict, total=False):
+    parent_id: Optional[str]
+    parent_step_run_id: Optional[str]
+    child_index: Optional[int]
+    child_key: Optional[str]
+    namespace: Optional[str]
+
+
+class ChildTriggerWorkflowOptions(TypedDict, total=False):
+    additional_metadata: Dict[str, str] | None = None
+    sticky: bool | None = None
+
+
+class ChildWorkflowRunDict(TypedDict, total=False):
+    workflow_name: str
+    input: Any
+    options: ChildTriggerWorkflowOptions
+    key: str | None = None
+
+
+class TriggerWorkflowOptions(ScheduleTriggerWorkflowOptions, total=False):
+    additional_metadata: Dict[str, str] | None = None
+    desired_worker_id: str | None = None
+    namespace: str | None = None
+
+
+class WorkflowRunDict(TypedDict, total=False):
+    workflow_name: str
+    input: Any
+    options: TriggerWorkflowOptions | None
+
+
+class DedupeViolationErr(Exception):
+    """Raised by the Hatchet library to indicate that a workflow has already been run with this deduplication value."""
+
+    pass
+
+
+class AdminClientBase:
+    pooled_workflow_listener: PooledWorkflowRunListener | None = None
+
+    def _prepare_workflow_request(
+        self, workflow_name: str, input: any, options: TriggerWorkflowOptions = None
+    ):
+        try:
+            payload_data = json.dumps(input)
+
+            try:
+                meta = (
+                    None
+                    if options is None or "additional_metadata" not in options
+                    else options["additional_metadata"]
+                )
+                if meta is not None:
+                    options = {
+                        **options,
+                        "additional_metadata": json.dumps(meta).encode("utf-8"),
+                    }
+            except json.JSONDecodeError as e:
+                raise ValueError(f"Error encoding payload: {e}")
+
+            return TriggerWorkflowRequest(
+                name=workflow_name, input=payload_data, **(options or {})
+            )
+        except json.JSONDecodeError as e:
+            raise ValueError(f"Error encoding payload: {e}")
+
+    def _prepare_put_workflow_request(
+        self,
+        name: str,
+        workflow: CreateWorkflowVersionOpts | WorkflowMeta,
+        overrides: CreateWorkflowVersionOpts | None = None,
+    ):
+        try:
+            opts: CreateWorkflowVersionOpts
+
+            if isinstance(workflow, CreateWorkflowVersionOpts):
+                opts = workflow
+            else:
+                opts = workflow.get_create_opts(self.client.config.namespace)
+
+            if overrides is not None:
+                opts.MergeFrom(overrides)
+
+            opts.name = name
+
+            return PutWorkflowRequest(
+                opts=opts,
+            )
+        except grpc.RpcError as e:
+            raise ValueError(f"Could not put workflow: {e}")
+
+    def _prepare_schedule_workflow_request(
+        self,
+        name: str,
+        schedules: List[Union[datetime, timestamp_pb2.Timestamp]],
+        input={},
+        options: ScheduleTriggerWorkflowOptions = None,
+    ):
+        timestamp_schedules = []
+        for schedule in schedules:
+            if isinstance(schedule, datetime):
+                t = schedule.timestamp()
+                seconds = int(t)
+                nanos = int(t % 1 * 1e9)
+                timestamp = timestamp_pb2.Timestamp(seconds=seconds, nanos=nanos)
+                timestamp_schedules.append(timestamp)
+            elif isinstance(schedule, timestamp_pb2.Timestamp):
+                timestamp_schedules.append(schedule)
+            else:
+                raise ValueError(
+                    "Invalid schedule type. Must be datetime or timestamp_pb2.Timestamp."
+                )
+
+        return ScheduleWorkflowRequest(
+            name=name,
+            schedules=timestamp_schedules,
+            input=json.dumps(input),
+            **(options or {}),
+        )
+
+
+T = TypeVar("T")
+
+
+class AdminClientAioImpl(AdminClientBase):
+    def __init__(self, config: ClientConfig):
+        aio_conn = new_conn(config, True)
+        self.config = config
+        self.aio_client = WorkflowServiceStub(aio_conn)
+        self.token = config.token
+        self.listener_client = new_listener(config)
+        self.namespace = config.namespace
+
+    async def run(
+        self,
+        function: Union[str, Callable[[Any], T]],
+        input: any,
+        options: TriggerWorkflowOptions = None,
+    ) -> "RunRef[T]":
+        workflow_name = function
+
+        if not isinstance(function, str):
+            workflow_name = function.function_name
+
+        wrr = await self.run_workflow(workflow_name, input, options)
+
+        return RunRef[T](
+            wrr.workflow_run_id, wrr.workflow_listener, wrr.workflow_run_event_listener
+        )
+
+    ## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
+    @tenacity_retry
+    async def run_workflow(
+        self, workflow_name: str, input: any, options: TriggerWorkflowOptions = None
+    ) -> WorkflowRunRef:
+        try:
+            if not self.pooled_workflow_listener:
+                self.pooled_workflow_listener = PooledWorkflowRunListener(self.config)
+
+            namespace = self.namespace
+
+            if (
+                options is not None
+                and "namespace" in options
+                and options["namespace"] is not None
+            ):
+                namespace = options.pop("namespace")
+
+            if namespace != "" and not workflow_name.startswith(self.namespace):
+                workflow_name = f"{namespace}{workflow_name}"
+
+            request = self._prepare_workflow_request(workflow_name, input, options)
+
+            resp: TriggerWorkflowResponse = await self.aio_client.TriggerWorkflow(
+                request,
+                metadata=get_metadata(self.token),
+            )
+
+            return WorkflowRunRef(
+                workflow_run_id=resp.workflow_run_id,
+                workflow_listener=self.pooled_workflow_listener,
+                workflow_run_event_listener=self.listener_client,
+            )
+        except (grpc.RpcError, grpc.aio.AioRpcError) as e:
+            if e.code() == grpc.StatusCode.ALREADY_EXISTS:
+                raise DedupeViolationErr(e.details())
+
+            raise e
+
+    ## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
+    @tenacity_retry
+    async def run_workflows(
+        self,
+        workflows: list[WorkflowRunDict],
+        options: TriggerWorkflowOptions | None = None,
+    ) -> List[WorkflowRunRef]:
+        if len(workflows) == 0:
+            raise ValueError("No workflows to run")
+
+        if not self.pooled_workflow_listener:
+            self.pooled_workflow_listener = PooledWorkflowRunListener(self.config)
+
+        namespace = self.namespace
+
+        if (
+            options is not None
+            and "namespace" in options
+            and options["namespace"] is not None
+        ):
+            namespace = options["namespace"]
+            del options["namespace"]
+
+        workflow_run_requests: TriggerWorkflowRequest = []
+
+        for workflow in workflows:
+            workflow_name = workflow["workflow_name"]
+            input_data = workflow["input"]
+            options = workflow["options"]
+
+            if namespace != "" and not workflow_name.startswith(self.namespace):
+                workflow_name = f"{namespace}{workflow_name}"
+
+            # Prepare and trigger workflow for each workflow name and input
+            request = self._prepare_workflow_request(workflow_name, input_data, options)
+            workflow_run_requests.append(request)
+
+        request = BulkTriggerWorkflowRequest(workflows=workflow_run_requests)
+
+        resp: BulkTriggerWorkflowResponse = await self.aio_client.BulkTriggerWorkflow(
+            request,
+            metadata=get_metadata(self.token),
+        )
+
+        return [
+            WorkflowRunRef(
+                workflow_run_id=workflow_run_id,
+                workflow_listener=self.pooled_workflow_listener,
+                workflow_run_event_listener=self.listener_client,
+            )
+            for workflow_run_id in resp.workflow_run_ids
+        ]
+
+    @tenacity_retry
+    async def put_workflow(
+        self,
+        name: str,
+        workflow: CreateWorkflowVersionOpts | WorkflowMeta,
+        overrides: CreateWorkflowVersionOpts | None = None,
+    ) -> WorkflowVersion:
+        opts = self._prepare_put_workflow_request(name, workflow, overrides)
+
+        return await self.aio_client.PutWorkflow(
+            opts,
+            metadata=get_metadata(self.token),
+        )
+
+    @tenacity_retry
+    async def put_rate_limit(
+        self,
+        key: str,
+        limit: int,
+        duration: RateLimitDuration = RateLimitDuration.SECOND,
+    ):
+        await self.aio_client.PutRateLimit(
+            PutRateLimitRequest(
+                key=key,
+                limit=limit,
+                duration=duration,
+            ),
+            metadata=get_metadata(self.token),
+        )
+
+    @tenacity_retry
+    async def schedule_workflow(
+        self,
+        name: str,
+        schedules: List[Union[datetime, timestamp_pb2.Timestamp]],
+        input={},
+        options: ScheduleTriggerWorkflowOptions = None,
+    ) -> WorkflowVersion:
+        try:
+            namespace = self.namespace
+
+            if (
+                options is not None
+                and "namespace" in options
+                and options["namespace"] is not None
+            ):
+                namespace = options["namespace"]
+                del options["namespace"]
+
+            if namespace != "" and not name.startswith(self.namespace):
+                name = f"{namespace}{name}"
+
+            request = self._prepare_schedule_workflow_request(
+                name, schedules, input, options
+            )
+
+            return await self.aio_client.ScheduleWorkflow(
+                request,
+                metadata=get_metadata(self.token),
+            )
+        except (grpc.aio.AioRpcError, grpc.RpcError) as e:
+            if e.code() == grpc.StatusCode.ALREADY_EXISTS:
+                raise DedupeViolationErr(e.details())
+
+            raise e
+
+
+class AdminClient(AdminClientBase):
+    def __init__(self, config: ClientConfig):
+        conn = new_conn(config)
+        self.config = config
+        self.client = WorkflowServiceStub(conn)
+        self.aio = AdminClientAioImpl(config)
+        self.token = config.token
+        self.listener_client = new_listener(config)
+        self.namespace = config.namespace
+
+    @tenacity_retry
+    def put_workflow(
+        self,
+        name: str,
+        workflow: CreateWorkflowVersionOpts | WorkflowMeta,
+        overrides: CreateWorkflowVersionOpts | None = None,
+    ) -> WorkflowVersion:
+        opts = self._prepare_put_workflow_request(name, workflow, overrides)
+
+        resp: WorkflowVersion = self.client.PutWorkflow(
+            opts,
+            metadata=get_metadata(self.token),
+        )
+
+        return resp
+
+    @tenacity_retry
+    def put_rate_limit(
+        self,
+        key: str,
+        limit: int,
+        duration: Union[RateLimitDuration.Value, str] = RateLimitDuration.SECOND,
+    ):
+        self.client.PutRateLimit(
+            PutRateLimitRequest(
+                key=key,
+                limit=limit,
+                duration=duration,
+            ),
+            metadata=get_metadata(self.token),
+        )
+
+    @tenacity_retry
+    def schedule_workflow(
+        self,
+        name: str,
+        schedules: List[Union[datetime, timestamp_pb2.Timestamp]],
+        input={},
+        options: ScheduleTriggerWorkflowOptions = None,
+    ) -> WorkflowVersion:
+        try:
+            namespace = self.namespace
+
+            if (
+                options is not None
+                and "namespace" in options
+                and options["namespace"] is not None
+            ):
+                namespace = options["namespace"]
+                del options["namespace"]
+
+            if namespace != "" and not name.startswith(self.namespace):
+                name = f"{namespace}{name}"
+
+            request = self._prepare_schedule_workflow_request(
+                name, schedules, input, options
+            )
+
+            return self.client.ScheduleWorkflow(
+                request,
+                metadata=get_metadata(self.token),
+            )
+        except (grpc.RpcError, grpc.aio.AioRpcError) as e:
+            if e.code() == grpc.StatusCode.ALREADY_EXISTS:
+                raise DedupeViolationErr(e.details())
+
+            raise e
+
+    ## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
+    @tenacity_retry
+    def run_workflow(
+        self, workflow_name: str, input: any, options: TriggerWorkflowOptions = None
+    ) -> WorkflowRunRef:
+        try:
+            if not self.pooled_workflow_listener:
+                self.pooled_workflow_listener = PooledWorkflowRunListener(self.config)
+
+            namespace = self.namespace
+
+            ## TODO: Factor this out - it's repeated a lot of places
+            if (
+                options is not None
+                and "namespace" in options
+                and options["namespace"] is not None
+            ):
+                namespace = options.pop("namespace")
+
+            if namespace != "" and not workflow_name.startswith(self.namespace):
+                workflow_name = f"{namespace}{workflow_name}"
+
+            request = self._prepare_workflow_request(workflow_name, input, options)
+
+            resp: TriggerWorkflowResponse = self.client.TriggerWorkflow(
+                request,
+                metadata=get_metadata(self.token),
+            )
+
+            return WorkflowRunRef(
+                workflow_run_id=resp.workflow_run_id,
+                workflow_listener=self.pooled_workflow_listener,
+                workflow_run_event_listener=self.listener_client,
+            )
+        except (grpc.RpcError, grpc.aio.AioRpcError) as e:
+            if e.code() == grpc.StatusCode.ALREADY_EXISTS:
+                raise DedupeViolationErr(e.details())
+
+            raise e
+
+    ## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
+    @tenacity_retry
+    def run_workflows(
+        self, workflows: List[WorkflowRunDict], options: TriggerWorkflowOptions = None
+    ) -> list[WorkflowRunRef]:
+        workflow_run_requests: TriggerWorkflowRequest = []
+        if not self.pooled_workflow_listener:
+            self.pooled_workflow_listener = PooledWorkflowRunListener(self.config)
+
+        for workflow in workflows:
+            workflow_name = workflow["workflow_name"]
+            input_data = workflow["input"]
+            options = workflow["options"]
+
+            namespace = self.namespace
+
+            if (
+                options is not None
+                and "namespace" in options
+                and options["namespace"] is not None
+            ):
+                namespace = options["namespace"]
+                del options["namespace"]
+
+            if namespace != "" and not workflow_name.startswith(self.namespace):
+                workflow_name = f"{namespace}{workflow_name}"
+
+            # Prepare and trigger workflow for each workflow name and input
+            request = self._prepare_workflow_request(workflow_name, input_data, options)
+
+            workflow_run_requests.append(request)
+
+            request = BulkTriggerWorkflowRequest(workflows=workflow_run_requests)
+
+        resp: BulkTriggerWorkflowResponse = self.client.BulkTriggerWorkflow(
+            request,
+            metadata=get_metadata(self.token),
+        )
+
+        return [
+            WorkflowRunRef(
+                workflow_run_id=workflow_run_id,
+                workflow_listener=self.pooled_workflow_listener,
+                workflow_run_event_listener=self.listener_client,
+            )
+            for workflow_run_id in resp.workflow_run_ids
+        ]
+
+    def run(
+        self,
+        function: Union[str, Callable[[Any], T]],
+        input: any,
+        options: TriggerWorkflowOptions = None,
+    ) -> "RunRef[T]":
+        workflow_name = function
+
+        if not isinstance(function, str):
+            workflow_name = function.function_name
+
+        wrr = self.run_workflow(workflow_name, input, options)
+
+        return RunRef[T](
+            wrr.workflow_run_id, wrr.workflow_listener, wrr.workflow_run_event_listener
+        )
+
+    def get_workflow_run(self, workflow_run_id: str) -> WorkflowRunRef:
+        try:
+            if not self.pooled_workflow_listener:
+                self.pooled_workflow_listener = PooledWorkflowRunListener(self.config)
+
+            return WorkflowRunRef(
+                workflow_run_id=workflow_run_id,
+                workflow_listener=self.pooled_workflow_listener,
+                workflow_run_event_listener=self.listener_client,
+            )
+        except grpc.RpcError as e:
+            raise ValueError(f"Could not get workflow run: {e}")
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/dispatcher/action_listener.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/dispatcher/action_listener.py
new file mode 100644
index 00000000..cf231a76
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/dispatcher/action_listener.py
@@ -0,0 +1,423 @@
+import asyncio
+import json
+import time
+from dataclasses import dataclass, field
+from typing import Any, AsyncGenerator, List, Optional
+
+import grpc
+from grpc._cython import cygrpc
+
+from hatchet_sdk.clients.event_ts import Event_ts, read_with_interrupt
+from hatchet_sdk.clients.run_event_listener import (
+    DEFAULT_ACTION_LISTENER_RETRY_INTERVAL,
+)
+from hatchet_sdk.connection import new_conn
+from hatchet_sdk.contracts.dispatcher_pb2 import (
+    ActionType,
+    AssignedAction,
+    HeartbeatRequest,
+    WorkerLabels,
+    WorkerListenRequest,
+    WorkerUnsubscribeRequest,
+)
+from hatchet_sdk.contracts.dispatcher_pb2_grpc import DispatcherStub
+from hatchet_sdk.logger import logger
+from hatchet_sdk.utils.backoff import exp_backoff_sleep
+from hatchet_sdk.utils.serialization import flatten
+
+from ...loader import ClientConfig
+from ...metadata import get_metadata
+from ..events import proto_timestamp_now
+
+DEFAULT_ACTION_TIMEOUT = 600  # seconds
+
+
+DEFAULT_ACTION_LISTENER_RETRY_INTERVAL = 5  # seconds
+DEFAULT_ACTION_LISTENER_RETRY_COUNT = 15
+
+
+@dataclass
+class GetActionListenerRequest:
+    worker_name: str
+    services: List[str]
+    actions: List[str]
+    max_runs: Optional[int] = None
+    _labels: dict[str, str | int] = field(default_factory=dict)
+
+    labels: dict[str, WorkerLabels] = field(init=False)
+
+    def __post_init__(self):
+        self.labels = {}
+
+        for key, value in self._labels.items():
+            if isinstance(value, int):
+                self.labels[key] = WorkerLabels(intValue=value)
+            else:
+                self.labels[key] = WorkerLabels(strValue=str(value))
+
+
+@dataclass
+class Action:
+    worker_id: str
+    tenant_id: str
+    workflow_run_id: str
+    get_group_key_run_id: str
+    job_id: str
+    job_name: str
+    job_run_id: str
+    step_id: str
+    step_run_id: str
+    action_id: str
+    action_payload: str
+    action_type: ActionType
+    retry_count: int
+    additional_metadata: dict[str, str] | None = None
+
+    child_workflow_index: int | None = None
+    child_workflow_key: str | None = None
+    parent_workflow_run_id: str | None = None
+
+    def __post_init__(self):
+        if isinstance(self.additional_metadata, str) and self.additional_metadata != "":
+            try:
+                self.additional_metadata = json.loads(self.additional_metadata)
+            except json.JSONDecodeError:
+                # If JSON decoding fails, keep the original string
+                pass
+
+        # Ensure additional_metadata is always a dictionary
+        if not isinstance(self.additional_metadata, dict):
+            self.additional_metadata = {}
+
+    @property
+    def otel_attributes(self) -> dict[str, str | int]:
+        try:
+            payload_str = json.dumps(self.action_payload, default=str)
+        except Exception:
+            payload_str = str(self.action_payload)
+
+        attrs: dict[str, str | int | None] = {
+            "hatchet.tenant_id": self.tenant_id,
+            "hatchet.worker_id": self.worker_id,
+            "hatchet.workflow_run_id": self.workflow_run_id,
+            "hatchet.step_id": self.step_id,
+            "hatchet.step_run_id": self.step_run_id,
+            "hatchet.retry_count": self.retry_count,
+            "hatchet.parent_workflow_run_id": self.parent_workflow_run_id,
+            "hatchet.child_workflow_index": self.child_workflow_index,
+            "hatchet.child_workflow_key": self.child_workflow_key,
+            "hatchet.action_payload": payload_str,
+            "hatchet.workflow_name": self.job_name,
+            "hatchet.action_name": self.action_id,
+            "hatchet.get_group_key_run_id": self.get_group_key_run_id,
+        }
+
+        return {k: v for k, v in attrs.items() if v}
+
+
+START_STEP_RUN = 0
+CANCEL_STEP_RUN = 1
+START_GET_GROUP_KEY = 2
+
+
+@dataclass
+class ActionListener:
+    config: ClientConfig
+    worker_id: str
+
+    client: DispatcherStub = field(init=False)
+    aio_client: DispatcherStub = field(init=False)
+    token: str = field(init=False)
+    retries: int = field(default=0, init=False)
+    last_connection_attempt: float = field(default=0, init=False)
+    last_heartbeat_succeeded: bool = field(default=True, init=False)
+    time_last_hb_succeeded: float = field(default=9999999999999, init=False)
+    heartbeat_task: Optional[asyncio.Task] = field(default=None, init=False)
+    run_heartbeat: bool = field(default=True, init=False)
+    listen_strategy: str = field(default="v2", init=False)
+    stop_signal: bool = field(default=False, init=False)
+
+    missed_heartbeats: int = field(default=0, init=False)
+
+    def __post_init__(self):
+        self.client = DispatcherStub(new_conn(self.config))
+        self.aio_client = DispatcherStub(new_conn(self.config, True))
+        self.token = self.config.token
+
+    def is_healthy(self):
+        return self.last_heartbeat_succeeded
+
+    async def heartbeat(self):
+        # send a heartbeat every 4 seconds
+        heartbeat_delay = 4
+
+        while True:
+            if not self.run_heartbeat:
+                break
+
+            try:
+                logger.debug("sending heartbeat")
+                await self.aio_client.Heartbeat(
+                    HeartbeatRequest(
+                        workerId=self.worker_id,
+                        heartbeatAt=proto_timestamp_now(),
+                    ),
+                    timeout=5,
+                    metadata=get_metadata(self.token),
+                )
+
+                if self.last_heartbeat_succeeded is False:
+                    logger.info("listener established")
+
+                now = time.time()
+                diff = now - self.time_last_hb_succeeded
+                if diff > heartbeat_delay + 1:
+                    logger.warn(
+                        f"time since last successful heartbeat: {diff:.2f}s, expects {heartbeat_delay}s"
+                    )
+
+                self.last_heartbeat_succeeded = True
+                self.time_last_hb_succeeded = now
+                self.missed_heartbeats = 0
+            except grpc.RpcError as e:
+                self.missed_heartbeats = self.missed_heartbeats + 1
+                self.last_heartbeat_succeeded = False
+
+                if (
+                    e.code() == grpc.StatusCode.UNAVAILABLE
+                    or e.code() == grpc.StatusCode.FAILED_PRECONDITION
+                ):
+                    # todo case on "recvmsg:Connection reset by peer" for updates?
+                    if self.missed_heartbeats >= 3:
+                        # we don't reraise the error here, as we don't want to stop the heartbeat thread
+                        logger.error(
+                            f"⛔️ failed heartbeat ({self.missed_heartbeats}): {e.details()}"
+                        )
+                    elif self.missed_heartbeats > 1:
+                        logger.warning(
+                            f"failed to send heartbeat ({self.missed_heartbeats}): {e.details()}"
+                        )
+                else:
+                    logger.error(f"failed to send heartbeat: {e}")
+
+                if self.interrupt is not None:
+                    self.interrupt.set()
+
+                if e.code() == grpc.StatusCode.UNIMPLEMENTED:
+                    break
+            await asyncio.sleep(heartbeat_delay)
+
+    async def start_heartbeater(self):
+        if self.heartbeat_task is not None:
+            return
+
+        try:
+            loop = asyncio.get_event_loop()
+        except RuntimeError as e:
+            if str(e).startswith("There is no current event loop in thread"):
+                loop = asyncio.new_event_loop()
+                asyncio.set_event_loop(loop)
+            else:
+                raise e
+        self.heartbeat_task = loop.create_task(self.heartbeat())
+
+    def __aiter__(self):
+        return self._generator()
+
+    async def _generator(self) -> AsyncGenerator[Action, None]:
+        listener = None
+
+        while not self.stop_signal:
+            if listener is not None:
+                listener.cancel()
+
+            try:
+                listener = await self.get_listen_client()
+            except Exception:
+                logger.info("closing action listener loop")
+                yield None
+
+            try:
+                while not self.stop_signal:
+                    self.interrupt = Event_ts()
+                    t = asyncio.create_task(
+                        read_with_interrupt(listener, self.interrupt)
+                    )
+                    await self.interrupt.wait()
+
+                    if not t.done():
+                        # print a warning
+                        logger.warning(
+                            "Interrupted read_with_interrupt task of action listener"
+                        )
+
+                        t.cancel()
+                        listener.cancel()
+                        break
+
+                    assigned_action = t.result()
+
+                    if assigned_action is cygrpc.EOF:
+                        self.retries = self.retries + 1
+                        break
+
+                    self.retries = 0
+                    assigned_action: AssignedAction
+
+                    # Process the received action
+                    action_type = self.map_action_type(assigned_action.actionType)
+
+                    if (
+                        assigned_action.actionPayload is None
+                        or assigned_action.actionPayload == ""
+                    ):
+                        action_payload = None
+                    else:
+                        action_payload = self.parse_action_payload(
+                            assigned_action.actionPayload
+                        )
+
+                    action = Action(
+                        tenant_id=assigned_action.tenantId,
+                        worker_id=self.worker_id,
+                        workflow_run_id=assigned_action.workflowRunId,
+                        get_group_key_run_id=assigned_action.getGroupKeyRunId,
+                        job_id=assigned_action.jobId,
+                        job_name=assigned_action.jobName,
+                        job_run_id=assigned_action.jobRunId,
+                        step_id=assigned_action.stepId,
+                        step_run_id=assigned_action.stepRunId,
+                        action_id=assigned_action.actionId,
+                        action_payload=action_payload,
+                        action_type=action_type,
+                        retry_count=assigned_action.retryCount,
+                        additional_metadata=assigned_action.additional_metadata,
+                        child_workflow_index=assigned_action.child_workflow_index,
+                        child_workflow_key=assigned_action.child_workflow_key,
+                        parent_workflow_run_id=assigned_action.parent_workflow_run_id,
+                    )
+
+                    yield action
+            except grpc.RpcError as e:
+                self.last_heartbeat_succeeded = False
+
+                # Handle different types of errors
+                if e.code() == grpc.StatusCode.CANCELLED:
+                    # Context cancelled, unsubscribe and close
+                    logger.debug("Context cancelled, closing listener")
+                elif e.code() == grpc.StatusCode.DEADLINE_EXCEEDED:
+                    logger.info("Deadline exceeded, retrying subscription")
+                elif (
+                    self.listen_strategy == "v2"
+                    and e.code() == grpc.StatusCode.UNIMPLEMENTED
+                ):
+                    # ListenV2 is not available, fallback to Listen
+                    self.listen_strategy = "v1"
+                    self.run_heartbeat = False
+                    logger.info("ListenV2 not available, falling back to Listen")
+                else:
+                    # TODO retry
+                    if e.code() == grpc.StatusCode.UNAVAILABLE:
+                        logger.error(f"action listener error: {e.details()}")
+                    else:
+                        # Unknown error, report and break
+                        logger.error(f"action listener error: {e}")
+
+                    self.retries = self.retries + 1
+
+    def parse_action_payload(self, payload: str):
+        try:
+            payload_data = json.loads(payload)
+        except json.JSONDecodeError as e:
+            raise ValueError(f"Error decoding payload: {e}")
+        return payload_data
+
+    def map_action_type(self, action_type):
+        if action_type == ActionType.START_STEP_RUN:
+            return START_STEP_RUN
+        elif action_type == ActionType.CANCEL_STEP_RUN:
+            return CANCEL_STEP_RUN
+        elif action_type == ActionType.START_GET_GROUP_KEY:
+            return START_GET_GROUP_KEY
+        else:
+            # logger.error(f"Unknown action type: {action_type}")
+            return None
+
+    async def get_listen_client(self):
+        current_time = int(time.time())
+
+        if (
+            current_time - self.last_connection_attempt
+            > DEFAULT_ACTION_LISTENER_RETRY_INTERVAL
+        ):
+            # reset retries if last connection was long lived
+            self.retries = 0
+
+        if self.retries > DEFAULT_ACTION_LISTENER_RETRY_COUNT:
+            # TODO this is the problem case...
+            logger.error(
+                f"could not establish action listener connection after {DEFAULT_ACTION_LISTENER_RETRY_COUNT} retries"
+            )
+            self.run_heartbeat = False
+            raise Exception("retry_exhausted")
+        elif self.retries >= 1:
+            # logger.info
+            # if we are retrying, we wait for a bit. this should eventually be replaced with exp backoff + jitter
+            await exp_backoff_sleep(
+                self.retries, DEFAULT_ACTION_LISTENER_RETRY_INTERVAL
+            )
+
+            logger.info(
+                f"action listener connection interrupted, retrying... ({self.retries}/{DEFAULT_ACTION_LISTENER_RETRY_COUNT})"
+            )
+
+        self.aio_client = DispatcherStub(new_conn(self.config, True))
+
+        if self.listen_strategy == "v2":
+            # we should await for the listener to be established before
+            # starting the heartbeater
+            listener = self.aio_client.ListenV2(
+                WorkerListenRequest(workerId=self.worker_id),
+                timeout=self.config.listener_v2_timeout,
+                metadata=get_metadata(self.token),
+            )
+            await self.start_heartbeater()
+        else:
+            # if ListenV2 is not available, fallback to Listen
+            listener = self.aio_client.Listen(
+                WorkerListenRequest(workerId=self.worker_id),
+                timeout=DEFAULT_ACTION_TIMEOUT,
+                metadata=get_metadata(self.token),
+            )
+
+        self.last_connection_attempt = current_time
+
+        return listener
+
+    def cleanup(self):
+        self.run_heartbeat = False
+        self.heartbeat_task.cancel()
+
+        try:
+            self.unregister()
+        except Exception as e:
+            logger.error(f"failed to unregister: {e}")
+
+        if self.interrupt:
+            self.interrupt.set()
+
+    def unregister(self):
+        self.run_heartbeat = False
+        self.heartbeat_task.cancel()
+
+        try:
+            req = self.aio_client.Unsubscribe(
+                WorkerUnsubscribeRequest(workerId=self.worker_id),
+                timeout=5,
+                metadata=get_metadata(self.token),
+            )
+            if self.interrupt is not None:
+                self.interrupt.set()
+            return req
+        except grpc.RpcError as e:
+            raise Exception(f"Failed to unsubscribe: {e}")
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/dispatcher/dispatcher.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/dispatcher/dispatcher.py
new file mode 100644
index 00000000..407a80cc
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/dispatcher/dispatcher.py
@@ -0,0 +1,204 @@
+from typing import Any, cast
+
+from google.protobuf.timestamp_pb2 import Timestamp
+
+from hatchet_sdk.clients.dispatcher.action_listener import (
+    Action,
+    ActionListener,
+    GetActionListenerRequest,
+)
+from hatchet_sdk.clients.rest.tenacity_utils import tenacity_retry
+from hatchet_sdk.connection import new_conn
+from hatchet_sdk.contracts.dispatcher_pb2 import (
+    STEP_EVENT_TYPE_COMPLETED,
+    STEP_EVENT_TYPE_FAILED,
+    ActionEventResponse,
+    GroupKeyActionEvent,
+    GroupKeyActionEventType,
+    OverridesData,
+    RefreshTimeoutRequest,
+    ReleaseSlotRequest,
+    StepActionEvent,
+    StepActionEventType,
+    UpsertWorkerLabelsRequest,
+    WorkerLabels,
+    WorkerRegisterRequest,
+    WorkerRegisterResponse,
+)
+from hatchet_sdk.contracts.dispatcher_pb2_grpc import DispatcherStub
+
+from ...loader import ClientConfig
+from ...metadata import get_metadata
+
+DEFAULT_REGISTER_TIMEOUT = 30
+
+
+def new_dispatcher(config: ClientConfig) -> "DispatcherClient":
+    return DispatcherClient(config=config)
+
+
+class DispatcherClient:
+    config: ClientConfig
+
+    def __init__(self, config: ClientConfig):
+        conn = new_conn(config)
+        self.client = DispatcherStub(conn)  # type: ignore[no-untyped-call]
+
+        aio_conn = new_conn(config, True)
+        self.aio_client = DispatcherStub(aio_conn)  # type: ignore[no-untyped-call]
+        self.token = config.token
+        self.config = config
+
+    async def get_action_listener(
+        self, req: GetActionListenerRequest
+    ) -> ActionListener:
+
+        # Override labels with the preset labels
+        preset_labels = self.config.worker_preset_labels
+
+        for key, value in preset_labels.items():
+            req.labels[key] = WorkerLabels(strValue=str(value))
+
+        # Register the worker
+        response: WorkerRegisterResponse = await self.aio_client.Register(
+            WorkerRegisterRequest(
+                workerName=req.worker_name,
+                actions=req.actions,
+                services=req.services,
+                maxRuns=req.max_runs,
+                labels=req.labels,
+            ),
+            timeout=DEFAULT_REGISTER_TIMEOUT,
+            metadata=get_metadata(self.token),
+        )
+
+        return ActionListener(self.config, response.workerId)
+
+    async def send_step_action_event(
+        self, action: Action, event_type: StepActionEventType, payload: str
+    ) -> Any:
+        try:
+            return await self._try_send_step_action_event(action, event_type, payload)
+        except Exception as e:
+            # for step action events, send a failure event when we cannot send the completed event
+            if (
+                event_type == STEP_EVENT_TYPE_COMPLETED
+                or event_type == STEP_EVENT_TYPE_FAILED
+            ):
+                await self._try_send_step_action_event(
+                    action,
+                    STEP_EVENT_TYPE_FAILED,
+                    "Failed to send finished event: " + str(e),
+                )
+
+            return
+
+    @tenacity_retry
+    async def _try_send_step_action_event(
+        self, action: Action, event_type: StepActionEventType, payload: str
+    ) -> Any:
+        eventTimestamp = Timestamp()
+        eventTimestamp.GetCurrentTime()
+
+        event = StepActionEvent(
+            workerId=action.worker_id,
+            jobId=action.job_id,
+            jobRunId=action.job_run_id,
+            stepId=action.step_id,
+            stepRunId=action.step_run_id,
+            actionId=action.action_id,
+            eventTimestamp=eventTimestamp,
+            eventType=event_type,
+            eventPayload=payload,
+            retryCount=action.retry_count,
+        )
+
+        ## TODO: What does this return?
+        return await self.aio_client.SendStepActionEvent(
+            event,
+            metadata=get_metadata(self.token),
+        )
+
+    async def send_group_key_action_event(
+        self, action: Action, event_type: GroupKeyActionEventType, payload: str
+    ) -> Any:
+        eventTimestamp = Timestamp()
+        eventTimestamp.GetCurrentTime()
+
+        event = GroupKeyActionEvent(
+            workerId=action.worker_id,
+            workflowRunId=action.workflow_run_id,
+            getGroupKeyRunId=action.get_group_key_run_id,
+            actionId=action.action_id,
+            eventTimestamp=eventTimestamp,
+            eventType=event_type,
+            eventPayload=payload,
+        )
+
+        ## TODO: What does this return?
+        return await self.aio_client.SendGroupKeyActionEvent(
+            event,
+            metadata=get_metadata(self.token),
+        )
+
+    def put_overrides_data(self, data: OverridesData) -> ActionEventResponse:
+        return cast(
+            ActionEventResponse,
+            self.client.PutOverridesData(
+                data,
+                metadata=get_metadata(self.token),
+            ),
+        )
+
+    def release_slot(self, step_run_id: str) -> None:
+        self.client.ReleaseSlot(
+            ReleaseSlotRequest(stepRunId=step_run_id),
+            timeout=DEFAULT_REGISTER_TIMEOUT,
+            metadata=get_metadata(self.token),
+        )
+
+    def refresh_timeout(self, step_run_id: str, increment_by: str) -> None:
+        self.client.RefreshTimeout(
+            RefreshTimeoutRequest(
+                stepRunId=step_run_id,
+                incrementTimeoutBy=increment_by,
+            ),
+            timeout=DEFAULT_REGISTER_TIMEOUT,
+            metadata=get_metadata(self.token),
+        )
+
+    def upsert_worker_labels(
+        self, worker_id: str | None, labels: dict[str, str | int]
+    ) -> None:
+        worker_labels = {}
+
+        for key, value in labels.items():
+            if isinstance(value, int):
+                worker_labels[key] = WorkerLabels(intValue=value)
+            else:
+                worker_labels[key] = WorkerLabels(strValue=str(value))
+
+        self.client.UpsertWorkerLabels(
+            UpsertWorkerLabelsRequest(workerId=worker_id, labels=worker_labels),
+            timeout=DEFAULT_REGISTER_TIMEOUT,
+            metadata=get_metadata(self.token),
+        )
+
+    async def async_upsert_worker_labels(
+        self,
+        worker_id: str | None,
+        labels: dict[str, str | int],
+    ) -> None:
+        worker_labels = {}
+
+        for key, value in labels.items():
+            if isinstance(value, int):
+                worker_labels[key] = WorkerLabels(intValue=value)
+            else:
+                worker_labels[key] = WorkerLabels(strValue=str(value))
+
+        await self.aio_client.UpsertWorkerLabels(
+            UpsertWorkerLabelsRequest(workerId=worker_id, labels=worker_labels),
+            timeout=DEFAULT_REGISTER_TIMEOUT,
+            metadata=get_metadata(self.token),
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/event_ts.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/event_ts.py
new file mode 100644
index 00000000..1d3c3978
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/event_ts.py
@@ -0,0 +1,28 @@
+import asyncio
+from typing import Any
+
+
+class Event_ts(asyncio.Event):
+    """
+    Event_ts is a subclass of asyncio.Event that allows for thread-safe setting and clearing of the event.
+    """
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        if self._loop is None:
+            self._loop = asyncio.get_event_loop()
+
+    def set(self):
+        if not self._loop.is_closed():
+            self._loop.call_soon_threadsafe(super().set)
+
+    def clear(self):
+        self._loop.call_soon_threadsafe(super().clear)
+
+
+async def read_with_interrupt(listener: Any, interrupt: Event_ts):
+    try:
+        result = await listener.read()
+        return result
+    finally:
+        interrupt.set()
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/events.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/events.py
new file mode 100644
index 00000000..cf6a2721
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/events.py
@@ -0,0 +1,183 @@
+import asyncio
+import datetime
+import json
+from typing import Any, Dict, List, Optional, TypedDict
+from uuid import uuid4
+
+import grpc
+from google.protobuf import timestamp_pb2
+
+from hatchet_sdk.clients.rest.tenacity_utils import tenacity_retry
+from hatchet_sdk.contracts.events_pb2 import (
+    BulkPushEventRequest,
+    Event,
+    PushEventRequest,
+    PutLogRequest,
+    PutStreamEventRequest,
+)
+from hatchet_sdk.contracts.events_pb2_grpc import EventsServiceStub
+from hatchet_sdk.utils.serialization import flatten
+
+from ..loader import ClientConfig
+from ..metadata import get_metadata
+
+
+def new_event(conn, config: ClientConfig):
+    return EventClient(
+        client=EventsServiceStub(conn),
+        config=config,
+    )
+
+
+def proto_timestamp_now():
+    t = datetime.datetime.now().timestamp()
+    seconds = int(t)
+    nanos = int(t % 1 * 1e9)
+
+    return timestamp_pb2.Timestamp(seconds=seconds, nanos=nanos)
+
+
+class PushEventOptions(TypedDict, total=False):
+    additional_metadata: Dict[str, str] | None = None
+    namespace: str | None = None
+
+
+class BulkPushEventOptions(TypedDict, total=False):
+    namespace: str | None = None
+
+
+class BulkPushEventWithMetadata(TypedDict, total=False):
+    key: str
+    payload: Any
+    additional_metadata: Optional[Dict[str, Any]]  # Optional metadata
+
+
+class EventClient:
+    def __init__(self, client: EventsServiceStub, config: ClientConfig):
+        self.client = client
+        self.token = config.token
+        self.namespace = config.namespace
+
+    async def async_push(
+        self, event_key, payload, options: Optional[PushEventOptions] = None
+    ) -> Event:
+        return await asyncio.to_thread(
+            self.push, event_key=event_key, payload=payload, options=options
+        )
+
+    async def async_bulk_push(
+        self,
+        events: List[BulkPushEventWithMetadata],
+        options: Optional[BulkPushEventOptions] = None,
+    ) -> List[Event]:
+        return await asyncio.to_thread(self.bulk_push, events=events, options=options)
+
+    ## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
+    @tenacity_retry
+    def push(self, event_key, payload, options: PushEventOptions = None) -> Event:
+        namespace = self.namespace
+
+        if (
+            options is not None
+            and "namespace" in options
+            and options["namespace"] is not None
+        ):
+            namespace = options.pop("namespace")
+
+        namespaced_event_key = namespace + event_key
+
+        try:
+            meta = dict() if options is None else options["additional_metadata"]
+            meta_bytes = None if meta is None else json.dumps(meta).encode("utf-8")
+        except Exception as e:
+            raise ValueError(f"Error encoding meta: {e}")
+
+        try:
+            payload_bytes = json.dumps(payload).encode("utf-8")
+        except json.UnicodeEncodeError as e:
+            raise ValueError(f"Error encoding payload: {e}")
+
+        request = PushEventRequest(
+            key=namespaced_event_key,
+            payload=payload_bytes,
+            eventTimestamp=proto_timestamp_now(),
+            additionalMetadata=meta_bytes,
+        )
+
+        return self.client.Push(request, metadata=get_metadata(self.token))
+
+    ## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
+    @tenacity_retry
+    def bulk_push(
+        self,
+        events: List[BulkPushEventWithMetadata],
+        options: BulkPushEventOptions = None,
+    ) -> List[Event]:
+        namespace = self.namespace
+
+        if (
+            options is not None
+            and "namespace" in options
+            and options["namespace"] is not None
+        ):
+            namespace = options.pop("namespace")
+
+        bulk_events = []
+        for event in events:
+            event_key = namespace + event["key"]
+            payload = event["payload"]
+
+            try:
+                meta = event.get("additional_metadata", {})
+                meta_bytes = json.dumps(meta).encode("utf-8") if meta else None
+            except Exception as e:
+                raise ValueError(f"Error encoding meta: {e}")
+
+            try:
+                payload_bytes = json.dumps(payload).encode("utf-8")
+            except json.UnicodeEncodeError as e:
+                raise ValueError(f"Error encoding payload: {e}")
+
+            request = PushEventRequest(
+                key=event_key,
+                payload=payload_bytes,
+                eventTimestamp=proto_timestamp_now(),
+                additionalMetadata=meta_bytes,
+            )
+            bulk_events.append(request)
+
+        bulk_request = BulkPushEventRequest(events=bulk_events)
+
+        response = self.client.BulkPush(bulk_request, metadata=get_metadata(self.token))
+
+        return response.events
+
+    def log(self, message: str, step_run_id: str):
+        try:
+            request = PutLogRequest(
+                stepRunId=step_run_id,
+                createdAt=proto_timestamp_now(),
+                message=message,
+            )
+
+            self.client.PutLog(request, metadata=get_metadata(self.token))
+        except Exception as e:
+            raise ValueError(f"Error logging: {e}")
+
+    def stream(self, data: str | bytes, step_run_id: str):
+        try:
+            if isinstance(data, str):
+                data_bytes = data.encode("utf-8")
+            elif isinstance(data, bytes):
+                data_bytes = data
+            else:
+                raise ValueError("Invalid data type. Expected str, bytes, or file.")
+
+            request = PutStreamEventRequest(
+                stepRunId=step_run_id,
+                createdAt=proto_timestamp_now(),
+                message=data_bytes,
+            )
+            self.client.PutStreamEvent(request, metadata=get_metadata(self.token))
+        except Exception as e:
+            raise ValueError(f"Error putting stream event: {e}")
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/__init__.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/__init__.py
new file mode 100644
index 00000000..6d8bc27f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/__init__.py
@@ -0,0 +1,293 @@
+# coding: utf-8
+
+# flake8: noqa
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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"
+
+# import apis into sdk package
+from hatchet_sdk.clients.rest.api.api_token_api import APITokenApi
+from hatchet_sdk.clients.rest.api.default_api import DefaultApi
+from hatchet_sdk.clients.rest.api.event_api import EventApi
+from hatchet_sdk.clients.rest.api.github_api import GithubApi
+from hatchet_sdk.clients.rest.api.healthcheck_api import HealthcheckApi
+from hatchet_sdk.clients.rest.api.log_api import LogApi
+from hatchet_sdk.clients.rest.api.metadata_api import MetadataApi
+from hatchet_sdk.clients.rest.api.rate_limits_api import RateLimitsApi
+from hatchet_sdk.clients.rest.api.slack_api import SlackApi
+from hatchet_sdk.clients.rest.api.sns_api import SNSApi
+from hatchet_sdk.clients.rest.api.step_run_api import StepRunApi
+from hatchet_sdk.clients.rest.api.tenant_api import TenantApi
+from hatchet_sdk.clients.rest.api.user_api import UserApi
+from hatchet_sdk.clients.rest.api.worker_api import WorkerApi
+from hatchet_sdk.clients.rest.api.workflow_api import WorkflowApi
+from hatchet_sdk.clients.rest.api.workflow_run_api import WorkflowRunApi
+from hatchet_sdk.clients.rest.api_client import ApiClient
+
+# import ApiClient
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.configuration import Configuration
+from hatchet_sdk.clients.rest.exceptions import (
+    ApiAttributeError,
+    ApiException,
+    ApiKeyError,
+    ApiTypeError,
+    ApiValueError,
+    OpenApiException,
+)
+from hatchet_sdk.clients.rest.models.accept_invite_request import AcceptInviteRequest
+
+# import models into sdk package
+from hatchet_sdk.clients.rest.models.api_error import APIError
+from hatchet_sdk.clients.rest.models.api_errors import APIErrors
+from hatchet_sdk.clients.rest.models.api_meta import APIMeta
+from hatchet_sdk.clients.rest.models.api_meta_auth import APIMetaAuth
+from hatchet_sdk.clients.rest.models.api_meta_integration import APIMetaIntegration
+from hatchet_sdk.clients.rest.models.api_meta_posthog import APIMetaPosthog
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.api_token import APIToken
+from hatchet_sdk.clients.rest.models.bulk_create_event_request import (
+    BulkCreateEventRequest,
+)
+from hatchet_sdk.clients.rest.models.cancel_event_request import CancelEventRequest
+from hatchet_sdk.clients.rest.models.concurrency_limit_strategy import (
+    ConcurrencyLimitStrategy,
+)
+from hatchet_sdk.clients.rest.models.create_api_token_request import (
+    CreateAPITokenRequest,
+)
+from hatchet_sdk.clients.rest.models.create_api_token_response import (
+    CreateAPITokenResponse,
+)
+from hatchet_sdk.clients.rest.models.create_cron_workflow_trigger_request import (
+    CreateCronWorkflowTriggerRequest,
+)
+from hatchet_sdk.clients.rest.models.create_event_request import CreateEventRequest
+from hatchet_sdk.clients.rest.models.create_pull_request_from_step_run import (
+    CreatePullRequestFromStepRun,
+)
+from hatchet_sdk.clients.rest.models.create_sns_integration_request import (
+    CreateSNSIntegrationRequest,
+)
+from hatchet_sdk.clients.rest.models.create_tenant_alert_email_group_request import (
+    CreateTenantAlertEmailGroupRequest,
+)
+from hatchet_sdk.clients.rest.models.create_tenant_invite_request import (
+    CreateTenantInviteRequest,
+)
+from hatchet_sdk.clients.rest.models.create_tenant_request import CreateTenantRequest
+from hatchet_sdk.clients.rest.models.cron_workflows import CronWorkflows
+from hatchet_sdk.clients.rest.models.cron_workflows_list import CronWorkflowsList
+from hatchet_sdk.clients.rest.models.cron_workflows_method import CronWorkflowsMethod
+from hatchet_sdk.clients.rest.models.cron_workflows_order_by_field import (
+    CronWorkflowsOrderByField,
+)
+from hatchet_sdk.clients.rest.models.event import Event
+from hatchet_sdk.clients.rest.models.event_data import EventData
+from hatchet_sdk.clients.rest.models.event_key_list import EventKeyList
+from hatchet_sdk.clients.rest.models.event_list import EventList
+from hatchet_sdk.clients.rest.models.event_order_by_direction import (
+    EventOrderByDirection,
+)
+from hatchet_sdk.clients.rest.models.event_order_by_field import EventOrderByField
+from hatchet_sdk.clients.rest.models.event_update_cancel200_response import (
+    EventUpdateCancel200Response,
+)
+from hatchet_sdk.clients.rest.models.event_workflow_run_summary import (
+    EventWorkflowRunSummary,
+)
+from hatchet_sdk.clients.rest.models.events import Events
+from hatchet_sdk.clients.rest.models.get_step_run_diff_response import (
+    GetStepRunDiffResponse,
+)
+from hatchet_sdk.clients.rest.models.info_get_version200_response import (
+    InfoGetVersion200Response,
+)
+from hatchet_sdk.clients.rest.models.job import Job
+from hatchet_sdk.clients.rest.models.job_run import JobRun
+from hatchet_sdk.clients.rest.models.job_run_status import JobRunStatus
+from hatchet_sdk.clients.rest.models.list_api_tokens_response import (
+    ListAPITokensResponse,
+)
+from hatchet_sdk.clients.rest.models.list_pull_requests_response import (
+    ListPullRequestsResponse,
+)
+from hatchet_sdk.clients.rest.models.list_slack_webhooks import ListSlackWebhooks
+from hatchet_sdk.clients.rest.models.list_sns_integrations import ListSNSIntegrations
+from hatchet_sdk.clients.rest.models.log_line import LogLine
+from hatchet_sdk.clients.rest.models.log_line_level import LogLineLevel
+from hatchet_sdk.clients.rest.models.log_line_list import LogLineList
+from hatchet_sdk.clients.rest.models.log_line_order_by_direction import (
+    LogLineOrderByDirection,
+)
+from hatchet_sdk.clients.rest.models.log_line_order_by_field import LogLineOrderByField
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.pull_request import PullRequest
+from hatchet_sdk.clients.rest.models.pull_request_state import PullRequestState
+from hatchet_sdk.clients.rest.models.queue_metrics import QueueMetrics
+from hatchet_sdk.clients.rest.models.rate_limit import RateLimit
+from hatchet_sdk.clients.rest.models.rate_limit_list import RateLimitList
+from hatchet_sdk.clients.rest.models.rate_limit_order_by_direction import (
+    RateLimitOrderByDirection,
+)
+from hatchet_sdk.clients.rest.models.rate_limit_order_by_field import (
+    RateLimitOrderByField,
+)
+from hatchet_sdk.clients.rest.models.recent_step_runs import RecentStepRuns
+from hatchet_sdk.clients.rest.models.reject_invite_request import RejectInviteRequest
+from hatchet_sdk.clients.rest.models.replay_event_request import ReplayEventRequest
+from hatchet_sdk.clients.rest.models.replay_workflow_runs_request import (
+    ReplayWorkflowRunsRequest,
+)
+from hatchet_sdk.clients.rest.models.replay_workflow_runs_response import (
+    ReplayWorkflowRunsResponse,
+)
+from hatchet_sdk.clients.rest.models.rerun_step_run_request import RerunStepRunRequest
+from hatchet_sdk.clients.rest.models.schedule_workflow_run_request import (
+    ScheduleWorkflowRunRequest,
+)
+from hatchet_sdk.clients.rest.models.scheduled_run_status import ScheduledRunStatus
+from hatchet_sdk.clients.rest.models.scheduled_workflows import ScheduledWorkflows
+from hatchet_sdk.clients.rest.models.scheduled_workflows_list import (
+    ScheduledWorkflowsList,
+)
+from hatchet_sdk.clients.rest.models.scheduled_workflows_method import (
+    ScheduledWorkflowsMethod,
+)
+from hatchet_sdk.clients.rest.models.scheduled_workflows_order_by_field import (
+    ScheduledWorkflowsOrderByField,
+)
+from hatchet_sdk.clients.rest.models.semaphore_slots import SemaphoreSlots
+from hatchet_sdk.clients.rest.models.slack_webhook import SlackWebhook
+from hatchet_sdk.clients.rest.models.sns_integration import SNSIntegration
+from hatchet_sdk.clients.rest.models.step import Step
+from hatchet_sdk.clients.rest.models.step_run import StepRun
+from hatchet_sdk.clients.rest.models.step_run_archive import StepRunArchive
+from hatchet_sdk.clients.rest.models.step_run_archive_list import StepRunArchiveList
+from hatchet_sdk.clients.rest.models.step_run_diff import StepRunDiff
+from hatchet_sdk.clients.rest.models.step_run_event import StepRunEvent
+from hatchet_sdk.clients.rest.models.step_run_event_list import StepRunEventList
+from hatchet_sdk.clients.rest.models.step_run_event_reason import StepRunEventReason
+from hatchet_sdk.clients.rest.models.step_run_event_severity import StepRunEventSeverity
+from hatchet_sdk.clients.rest.models.step_run_status import StepRunStatus
+from hatchet_sdk.clients.rest.models.tenant import Tenant
+from hatchet_sdk.clients.rest.models.tenant_alert_email_group import (
+    TenantAlertEmailGroup,
+)
+from hatchet_sdk.clients.rest.models.tenant_alert_email_group_list import (
+    TenantAlertEmailGroupList,
+)
+from hatchet_sdk.clients.rest.models.tenant_alerting_settings import (
+    TenantAlertingSettings,
+)
+from hatchet_sdk.clients.rest.models.tenant_invite import TenantInvite
+from hatchet_sdk.clients.rest.models.tenant_invite_list import TenantInviteList
+from hatchet_sdk.clients.rest.models.tenant_list import TenantList
+from hatchet_sdk.clients.rest.models.tenant_member import TenantMember
+from hatchet_sdk.clients.rest.models.tenant_member_list import TenantMemberList
+from hatchet_sdk.clients.rest.models.tenant_member_role import TenantMemberRole
+from hatchet_sdk.clients.rest.models.tenant_queue_metrics import TenantQueueMetrics
+from hatchet_sdk.clients.rest.models.tenant_resource import TenantResource
+from hatchet_sdk.clients.rest.models.tenant_resource_limit import TenantResourceLimit
+from hatchet_sdk.clients.rest.models.tenant_resource_policy import TenantResourcePolicy
+from hatchet_sdk.clients.rest.models.tenant_step_run_queue_metrics import (
+    TenantStepRunQueueMetrics,
+)
+from hatchet_sdk.clients.rest.models.trigger_workflow_run_request import (
+    TriggerWorkflowRunRequest,
+)
+from hatchet_sdk.clients.rest.models.update_tenant_alert_email_group_request import (
+    UpdateTenantAlertEmailGroupRequest,
+)
+from hatchet_sdk.clients.rest.models.update_tenant_invite_request import (
+    UpdateTenantInviteRequest,
+)
+from hatchet_sdk.clients.rest.models.update_tenant_request import UpdateTenantRequest
+from hatchet_sdk.clients.rest.models.update_worker_request import UpdateWorkerRequest
+from hatchet_sdk.clients.rest.models.user import User
+from hatchet_sdk.clients.rest.models.user_change_password_request import (
+    UserChangePasswordRequest,
+)
+from hatchet_sdk.clients.rest.models.user_login_request import UserLoginRequest
+from hatchet_sdk.clients.rest.models.user_register_request import UserRegisterRequest
+from hatchet_sdk.clients.rest.models.user_tenant_memberships_list import (
+    UserTenantMembershipsList,
+)
+from hatchet_sdk.clients.rest.models.user_tenant_public import UserTenantPublic
+from hatchet_sdk.clients.rest.models.webhook_worker import WebhookWorker
+from hatchet_sdk.clients.rest.models.webhook_worker_create_request import (
+    WebhookWorkerCreateRequest,
+)
+from hatchet_sdk.clients.rest.models.webhook_worker_create_response import (
+    WebhookWorkerCreateResponse,
+)
+from hatchet_sdk.clients.rest.models.webhook_worker_created import WebhookWorkerCreated
+from hatchet_sdk.clients.rest.models.webhook_worker_list_response import (
+    WebhookWorkerListResponse,
+)
+from hatchet_sdk.clients.rest.models.webhook_worker_request import WebhookWorkerRequest
+from hatchet_sdk.clients.rest.models.webhook_worker_request_list_response import (
+    WebhookWorkerRequestListResponse,
+)
+from hatchet_sdk.clients.rest.models.webhook_worker_request_method import (
+    WebhookWorkerRequestMethod,
+)
+from hatchet_sdk.clients.rest.models.worker import Worker
+from hatchet_sdk.clients.rest.models.worker_label import WorkerLabel
+from hatchet_sdk.clients.rest.models.worker_list import WorkerList
+from hatchet_sdk.clients.rest.models.worker_runtime_info import WorkerRuntimeInfo
+from hatchet_sdk.clients.rest.models.worker_runtime_sdks import WorkerRuntimeSDKs
+from hatchet_sdk.clients.rest.models.worker_type import WorkerType
+from hatchet_sdk.clients.rest.models.workflow import Workflow
+from hatchet_sdk.clients.rest.models.workflow_concurrency import WorkflowConcurrency
+from hatchet_sdk.clients.rest.models.workflow_kind import WorkflowKind
+from hatchet_sdk.clients.rest.models.workflow_list import WorkflowList
+from hatchet_sdk.clients.rest.models.workflow_metrics import WorkflowMetrics
+from hatchet_sdk.clients.rest.models.workflow_run import WorkflowRun
+from hatchet_sdk.clients.rest.models.workflow_run_list import WorkflowRunList
+from hatchet_sdk.clients.rest.models.workflow_run_order_by_direction import (
+    WorkflowRunOrderByDirection,
+)
+from hatchet_sdk.clients.rest.models.workflow_run_order_by_field import (
+    WorkflowRunOrderByField,
+)
+from hatchet_sdk.clients.rest.models.workflow_run_shape import WorkflowRunShape
+from hatchet_sdk.clients.rest.models.workflow_run_status import WorkflowRunStatus
+from hatchet_sdk.clients.rest.models.workflow_run_triggered_by import (
+    WorkflowRunTriggeredBy,
+)
+from hatchet_sdk.clients.rest.models.workflow_runs_cancel_request import (
+    WorkflowRunsCancelRequest,
+)
+from hatchet_sdk.clients.rest.models.workflow_runs_metrics import WorkflowRunsMetrics
+from hatchet_sdk.clients.rest.models.workflow_runs_metrics_counts import (
+    WorkflowRunsMetricsCounts,
+)
+from hatchet_sdk.clients.rest.models.workflow_tag import WorkflowTag
+from hatchet_sdk.clients.rest.models.workflow_trigger_cron_ref import (
+    WorkflowTriggerCronRef,
+)
+from hatchet_sdk.clients.rest.models.workflow_trigger_event_ref import (
+    WorkflowTriggerEventRef,
+)
+from hatchet_sdk.clients.rest.models.workflow_triggers import WorkflowTriggers
+from hatchet_sdk.clients.rest.models.workflow_update_request import (
+    WorkflowUpdateRequest,
+)
+from hatchet_sdk.clients.rest.models.workflow_version import WorkflowVersion
+from hatchet_sdk.clients.rest.models.workflow_version_definition import (
+    WorkflowVersionDefinition,
+)
+from hatchet_sdk.clients.rest.models.workflow_version_meta import WorkflowVersionMeta
+from hatchet_sdk.clients.rest.models.workflow_workers_count import WorkflowWorkersCount
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/__init__.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/__init__.py
new file mode 100644
index 00000000..f6ecbe38
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/__init__.py
@@ -0,0 +1,19 @@
+# flake8: noqa
+
+# import apis into api package
+from hatchet_sdk.clients.rest.api.api_token_api import APITokenApi
+from hatchet_sdk.clients.rest.api.default_api import DefaultApi
+from hatchet_sdk.clients.rest.api.event_api import EventApi
+from hatchet_sdk.clients.rest.api.github_api import GithubApi
+from hatchet_sdk.clients.rest.api.healthcheck_api import HealthcheckApi
+from hatchet_sdk.clients.rest.api.log_api import LogApi
+from hatchet_sdk.clients.rest.api.metadata_api import MetadataApi
+from hatchet_sdk.clients.rest.api.rate_limits_api import RateLimitsApi
+from hatchet_sdk.clients.rest.api.slack_api import SlackApi
+from hatchet_sdk.clients.rest.api.sns_api import SNSApi
+from hatchet_sdk.clients.rest.api.step_run_api import StepRunApi
+from hatchet_sdk.clients.rest.api.tenant_api import TenantApi
+from hatchet_sdk.clients.rest.api.user_api import UserApi
+from hatchet_sdk.clients.rest.api.worker_api import WorkerApi
+from hatchet_sdk.clients.rest.api.workflow_api import WorkflowApi
+from hatchet_sdk.clients.rest.api.workflow_run_api import WorkflowRunApi
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/api_token_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/api_token_api.py
new file mode 100644
index 00000000..054ccc6b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/api_token_api.py
@@ -0,0 +1,858 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.models.create_api_token_request import (
+    CreateAPITokenRequest,
+)
+from hatchet_sdk.clients.rest.models.create_api_token_response import (
+    CreateAPITokenResponse,
+)
+from hatchet_sdk.clients.rest.models.list_api_tokens_response import (
+    ListAPITokensResponse,
+)
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class APITokenApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def api_token_create(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        create_api_token_request: Optional[CreateAPITokenRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> CreateAPITokenResponse:
+        """Create API Token
+
+        Create an API token for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param create_api_token_request:
+        :type create_api_token_request: CreateAPITokenRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._api_token_create_serialize(
+            tenant=tenant,
+            create_api_token_request=create_api_token_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "CreateAPITokenResponse",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def api_token_create_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        create_api_token_request: Optional[CreateAPITokenRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[CreateAPITokenResponse]:
+        """Create API Token
+
+        Create an API token for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param create_api_token_request:
+        :type create_api_token_request: CreateAPITokenRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._api_token_create_serialize(
+            tenant=tenant,
+            create_api_token_request=create_api_token_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "CreateAPITokenResponse",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def api_token_create_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        create_api_token_request: Optional[CreateAPITokenRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Create API Token
+
+        Create an API token for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param create_api_token_request:
+        :type create_api_token_request: CreateAPITokenRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._api_token_create_serialize(
+            tenant=tenant,
+            create_api_token_request=create_api_token_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "CreateAPITokenResponse",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _api_token_create_serialize(
+        self,
+        tenant,
+        create_api_token_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if create_api_token_request is not None:
+            _body_params = create_api_token_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants/{tenant}/api-tokens",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def api_token_list(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ListAPITokensResponse:
+        """List API Tokens
+
+        List API tokens for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._api_token_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ListAPITokensResponse",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def api_token_list_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[ListAPITokensResponse]:
+        """List API Tokens
+
+        List API tokens for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._api_token_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ListAPITokensResponse",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def api_token_list_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List API Tokens
+
+        List API tokens for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._api_token_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ListAPITokensResponse",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _api_token_list_serialize(
+        self,
+        tenant,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/api-tokens",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def api_token_update_revoke(
+        self,
+        api_token: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The API token"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Revoke API Token
+
+        Revoke an API token for a tenant
+
+        :param api_token: The API token (required)
+        :type api_token: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._api_token_update_revoke_serialize(
+            api_token=api_token,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def api_token_update_revoke_with_http_info(
+        self,
+        api_token: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The API token"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Revoke API Token
+
+        Revoke an API token for a tenant
+
+        :param api_token: The API token (required)
+        :type api_token: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._api_token_update_revoke_serialize(
+            api_token=api_token,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def api_token_update_revoke_without_preload_content(
+        self,
+        api_token: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The API token"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Revoke API Token
+
+        Revoke an API token for a tenant
+
+        :param api_token: The API token (required)
+        :type api_token: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._api_token_update_revoke_serialize(
+            api_token=api_token,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _api_token_update_revoke_serialize(
+        self,
+        api_token,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if api_token is not None:
+            _path_params["api-token"] = api_token
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/api-tokens/{api-token}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/default_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/default_api.py
new file mode 100644
index 00000000..c53e7f3d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/default_api.py
@@ -0,0 +1,2257 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.models.info_get_version200_response import (
+    InfoGetVersion200Response,
+)
+from hatchet_sdk.clients.rest.models.tenant_invite import TenantInvite
+from hatchet_sdk.clients.rest.models.update_tenant_invite_request import (
+    UpdateTenantInviteRequest,
+)
+from hatchet_sdk.clients.rest.models.webhook_worker_create_request import (
+    WebhookWorkerCreateRequest,
+)
+from hatchet_sdk.clients.rest.models.webhook_worker_created import WebhookWorkerCreated
+from hatchet_sdk.clients.rest.models.webhook_worker_list_response import (
+    WebhookWorkerListResponse,
+)
+from hatchet_sdk.clients.rest.models.webhook_worker_request_list_response import (
+    WebhookWorkerRequestListResponse,
+)
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class DefaultApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def info_get_version(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> InfoGetVersion200Response:
+        """We return the version for the currently running server
+
+        Get the version of the server
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._info_get_version_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "InfoGetVersion200Response",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def info_get_version_with_http_info(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[InfoGetVersion200Response]:
+        """We return the version for the currently running server
+
+        Get the version of the server
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._info_get_version_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "InfoGetVersion200Response",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def info_get_version_without_preload_content(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """We return the version for the currently running server
+
+        Get the version of the server
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._info_get_version_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "InfoGetVersion200Response",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _info_get_version_serialize(
+        self,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = []
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/version",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def monitoring_post_run_probe(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Detailed Health Probe For the Instance
+
+        Triggers a workflow to check the status of the instance
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._monitoring_post_run_probe_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def monitoring_post_run_probe_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Detailed Health Probe For the Instance
+
+        Triggers a workflow to check the status of the instance
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._monitoring_post_run_probe_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def monitoring_post_run_probe_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Detailed Health Probe For the Instance
+
+        Triggers a workflow to check the status of the instance
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._monitoring_post_run_probe_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _monitoring_post_run_probe_serialize(
+        self,
+        tenant,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/monitoring/{tenant}/probe",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def tenant_invite_delete(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        tenant_invite: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The tenant invite id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> TenantInvite:
+        """Delete invite
+
+        Deletes a tenant invite
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param tenant_invite: The tenant invite id (required)
+        :type tenant_invite: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_delete_serialize(
+            tenant=tenant,
+            tenant_invite=tenant_invite,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantInvite",
+            "400": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def tenant_invite_delete_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        tenant_invite: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The tenant invite id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[TenantInvite]:
+        """Delete invite
+
+        Deletes a tenant invite
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param tenant_invite: The tenant invite id (required)
+        :type tenant_invite: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_delete_serialize(
+            tenant=tenant,
+            tenant_invite=tenant_invite,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantInvite",
+            "400": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def tenant_invite_delete_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        tenant_invite: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The tenant invite id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Delete invite
+
+        Deletes a tenant invite
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param tenant_invite: The tenant invite id (required)
+        :type tenant_invite: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_delete_serialize(
+            tenant=tenant,
+            tenant_invite=tenant_invite,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantInvite",
+            "400": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _tenant_invite_delete_serialize(
+        self,
+        tenant,
+        tenant_invite,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if tenant_invite is not None:
+            _path_params["tenant-invite"] = tenant_invite
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="DELETE",
+            resource_path="/api/v1/tenants/{tenant}/invites/{tenant-invite}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def tenant_invite_update(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        tenant_invite: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The tenant invite id",
+            ),
+        ],
+        update_tenant_invite_request: Annotated[
+            UpdateTenantInviteRequest, Field(description="The tenant invite to update")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> TenantInvite:
+        """Update invite
+
+        Updates a tenant invite
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param tenant_invite: The tenant invite id (required)
+        :type tenant_invite: str
+        :param update_tenant_invite_request: The tenant invite to update (required)
+        :type update_tenant_invite_request: UpdateTenantInviteRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_update_serialize(
+            tenant=tenant,
+            tenant_invite=tenant_invite,
+            update_tenant_invite_request=update_tenant_invite_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantInvite",
+            "400": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def tenant_invite_update_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        tenant_invite: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The tenant invite id",
+            ),
+        ],
+        update_tenant_invite_request: Annotated[
+            UpdateTenantInviteRequest, Field(description="The tenant invite to update")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[TenantInvite]:
+        """Update invite
+
+        Updates a tenant invite
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param tenant_invite: The tenant invite id (required)
+        :type tenant_invite: str
+        :param update_tenant_invite_request: The tenant invite to update (required)
+        :type update_tenant_invite_request: UpdateTenantInviteRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_update_serialize(
+            tenant=tenant,
+            tenant_invite=tenant_invite,
+            update_tenant_invite_request=update_tenant_invite_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantInvite",
+            "400": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def tenant_invite_update_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        tenant_invite: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The tenant invite id",
+            ),
+        ],
+        update_tenant_invite_request: Annotated[
+            UpdateTenantInviteRequest, Field(description="The tenant invite to update")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Update invite
+
+        Updates a tenant invite
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param tenant_invite: The tenant invite id (required)
+        :type tenant_invite: str
+        :param update_tenant_invite_request: The tenant invite to update (required)
+        :type update_tenant_invite_request: UpdateTenantInviteRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_update_serialize(
+            tenant=tenant,
+            tenant_invite=tenant_invite,
+            update_tenant_invite_request=update_tenant_invite_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantInvite",
+            "400": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _tenant_invite_update_serialize(
+        self,
+        tenant,
+        tenant_invite,
+        update_tenant_invite_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if tenant_invite is not None:
+            _path_params["tenant-invite"] = tenant_invite
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if update_tenant_invite_request is not None:
+            _body_params = update_tenant_invite_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="PATCH",
+            resource_path="/api/v1/tenants/{tenant}/invites/{tenant-invite}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def webhook_create(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        webhook_worker_create_request: Optional[WebhookWorkerCreateRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> WebhookWorkerCreated:
+        """Create a webhook
+
+        Creates a webhook
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param webhook_worker_create_request:
+        :type webhook_worker_create_request: WebhookWorkerCreateRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._webhook_create_serialize(
+            tenant=tenant,
+            webhook_worker_create_request=webhook_worker_create_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WebhookWorkerCreated",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def webhook_create_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        webhook_worker_create_request: Optional[WebhookWorkerCreateRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[WebhookWorkerCreated]:
+        """Create a webhook
+
+        Creates a webhook
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param webhook_worker_create_request:
+        :type webhook_worker_create_request: WebhookWorkerCreateRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._webhook_create_serialize(
+            tenant=tenant,
+            webhook_worker_create_request=webhook_worker_create_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WebhookWorkerCreated",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def webhook_create_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        webhook_worker_create_request: Optional[WebhookWorkerCreateRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Create a webhook
+
+        Creates a webhook
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param webhook_worker_create_request:
+        :type webhook_worker_create_request: WebhookWorkerCreateRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._webhook_create_serialize(
+            tenant=tenant,
+            webhook_worker_create_request=webhook_worker_create_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WebhookWorkerCreated",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _webhook_create_serialize(
+        self,
+        tenant,
+        webhook_worker_create_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if webhook_worker_create_request is not None:
+            _body_params = webhook_worker_create_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants/{tenant}/webhook-workers",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def webhook_delete(
+        self,
+        webhook: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The webhook id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Delete a webhook
+
+        Deletes a webhook
+
+        :param webhook: The webhook id (required)
+        :type webhook: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._webhook_delete_serialize(
+            webhook=webhook,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def webhook_delete_with_http_info(
+        self,
+        webhook: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The webhook id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Delete a webhook
+
+        Deletes a webhook
+
+        :param webhook: The webhook id (required)
+        :type webhook: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._webhook_delete_serialize(
+            webhook=webhook,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def webhook_delete_without_preload_content(
+        self,
+        webhook: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The webhook id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Delete a webhook
+
+        Deletes a webhook
+
+        :param webhook: The webhook id (required)
+        :type webhook: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._webhook_delete_serialize(
+            webhook=webhook,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _webhook_delete_serialize(
+        self,
+        webhook,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if webhook is not None:
+            _path_params["webhook"] = webhook
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="DELETE",
+            resource_path="/api/v1/webhook-workers/{webhook}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def webhook_list(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> WebhookWorkerListResponse:
+        """List webhooks
+
+        Lists all webhooks
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._webhook_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WebhookWorkerListResponse",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def webhook_list_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[WebhookWorkerListResponse]:
+        """List webhooks
+
+        Lists all webhooks
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._webhook_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WebhookWorkerListResponse",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def webhook_list_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List webhooks
+
+        Lists all webhooks
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._webhook_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WebhookWorkerListResponse",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _webhook_list_serialize(
+        self,
+        tenant,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/webhook-workers",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def webhook_requests_list(
+        self,
+        webhook: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The webhook id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> WebhookWorkerRequestListResponse:
+        """List webhook requests
+
+        Lists all requests for a webhook
+
+        :param webhook: The webhook id (required)
+        :type webhook: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._webhook_requests_list_serialize(
+            webhook=webhook,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WebhookWorkerRequestListResponse",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def webhook_requests_list_with_http_info(
+        self,
+        webhook: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The webhook id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[WebhookWorkerRequestListResponse]:
+        """List webhook requests
+
+        Lists all requests for a webhook
+
+        :param webhook: The webhook id (required)
+        :type webhook: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._webhook_requests_list_serialize(
+            webhook=webhook,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WebhookWorkerRequestListResponse",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def webhook_requests_list_without_preload_content(
+        self,
+        webhook: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The webhook id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List webhook requests
+
+        Lists all requests for a webhook
+
+        :param webhook: The webhook id (required)
+        :type webhook: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._webhook_requests_list_serialize(
+            webhook=webhook,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WebhookWorkerRequestListResponse",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _webhook_requests_list_serialize(
+        self,
+        webhook,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if webhook is not None:
+            _path_params["webhook"] = webhook
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/webhook-workers/{webhook}/requests",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/event_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/event_api.py
new file mode 100644
index 00000000..d66485e3
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/event_api.py
@@ -0,0 +1,2548 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.models.bulk_create_event_request import (
+    BulkCreateEventRequest,
+)
+from hatchet_sdk.clients.rest.models.cancel_event_request import CancelEventRequest
+from hatchet_sdk.clients.rest.models.create_event_request import CreateEventRequest
+from hatchet_sdk.clients.rest.models.event import Event
+from hatchet_sdk.clients.rest.models.event_data import EventData
+from hatchet_sdk.clients.rest.models.event_key_list import EventKeyList
+from hatchet_sdk.clients.rest.models.event_list import EventList
+from hatchet_sdk.clients.rest.models.event_order_by_direction import (
+    EventOrderByDirection,
+)
+from hatchet_sdk.clients.rest.models.event_order_by_field import EventOrderByField
+from hatchet_sdk.clients.rest.models.event_update_cancel200_response import (
+    EventUpdateCancel200Response,
+)
+from hatchet_sdk.clients.rest.models.events import Events
+from hatchet_sdk.clients.rest.models.replay_event_request import ReplayEventRequest
+from hatchet_sdk.clients.rest.models.workflow_run_status import WorkflowRunStatus
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class EventApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def event_create(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        create_event_request: Annotated[
+            CreateEventRequest, Field(description="The event to create")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> Event:
+        """Create event
+
+        Creates a new event.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param create_event_request: The event to create (required)
+        :type create_event_request: CreateEventRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_create_serialize(
+            tenant=tenant,
+            create_event_request=create_event_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Event",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def event_create_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        create_event_request: Annotated[
+            CreateEventRequest, Field(description="The event to create")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[Event]:
+        """Create event
+
+        Creates a new event.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param create_event_request: The event to create (required)
+        :type create_event_request: CreateEventRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_create_serialize(
+            tenant=tenant,
+            create_event_request=create_event_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Event",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def event_create_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        create_event_request: Annotated[
+            CreateEventRequest, Field(description="The event to create")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Create event
+
+        Creates a new event.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param create_event_request: The event to create (required)
+        :type create_event_request: CreateEventRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_create_serialize(
+            tenant=tenant,
+            create_event_request=create_event_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Event",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _event_create_serialize(
+        self,
+        tenant,
+        create_event_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if create_event_request is not None:
+            _body_params = create_event_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants/{tenant}/events",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def event_create_bulk(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        bulk_create_event_request: Annotated[
+            BulkCreateEventRequest, Field(description="The events to create")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> Events:
+        """Bulk Create events
+
+        Bulk creates new events.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param bulk_create_event_request: The events to create (required)
+        :type bulk_create_event_request: BulkCreateEventRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_create_bulk_serialize(
+            tenant=tenant,
+            bulk_create_event_request=bulk_create_event_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Events",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def event_create_bulk_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        bulk_create_event_request: Annotated[
+            BulkCreateEventRequest, Field(description="The events to create")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[Events]:
+        """Bulk Create events
+
+        Bulk creates new events.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param bulk_create_event_request: The events to create (required)
+        :type bulk_create_event_request: BulkCreateEventRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_create_bulk_serialize(
+            tenant=tenant,
+            bulk_create_event_request=bulk_create_event_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Events",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def event_create_bulk_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        bulk_create_event_request: Annotated[
+            BulkCreateEventRequest, Field(description="The events to create")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Bulk Create events
+
+        Bulk creates new events.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param bulk_create_event_request: The events to create (required)
+        :type bulk_create_event_request: BulkCreateEventRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_create_bulk_serialize(
+            tenant=tenant,
+            bulk_create_event_request=bulk_create_event_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Events",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _event_create_bulk_serialize(
+        self,
+        tenant,
+        bulk_create_event_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if bulk_create_event_request is not None:
+            _body_params = bulk_create_event_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants/{tenant}/events/bulk",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def event_data_get(
+        self,
+        event: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The event id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> EventData:
+        """Get event data
+
+        Get the data for an event.
+
+        :param event: The event id (required)
+        :type event: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_data_get_serialize(
+            event=event,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventData",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def event_data_get_with_http_info(
+        self,
+        event: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The event id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[EventData]:
+        """Get event data
+
+        Get the data for an event.
+
+        :param event: The event id (required)
+        :type event: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_data_get_serialize(
+            event=event,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventData",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def event_data_get_without_preload_content(
+        self,
+        event: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The event id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get event data
+
+        Get the data for an event.
+
+        :param event: The event id (required)
+        :type event: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_data_get_serialize(
+            event=event,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventData",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _event_data_get_serialize(
+        self,
+        event,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if event is not None:
+            _path_params["event"] = event
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/events/{event}/data",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def event_get(
+        self,
+        event: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The event id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> Event:
+        """Get event data
+
+        Get an event.
+
+        :param event: The event id (required)
+        :type event: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_get_serialize(
+            event=event,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Event",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def event_get_with_http_info(
+        self,
+        event: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The event id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[Event]:
+        """Get event data
+
+        Get an event.
+
+        :param event: The event id (required)
+        :type event: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_get_serialize(
+            event=event,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Event",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def event_get_without_preload_content(
+        self,
+        event: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The event id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get event data
+
+        Get an event.
+
+        :param event: The event id (required)
+        :type event: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_get_serialize(
+            event=event,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Event",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _event_get_serialize(
+        self,
+        event,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if event is not None:
+            _path_params["event"] = event
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/events/{event}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def event_key_list(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> EventKeyList:
+        """List event keys
+
+        Lists all event keys for a tenant.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_key_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventKeyList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def event_key_list_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[EventKeyList]:
+        """List event keys
+
+        Lists all event keys for a tenant.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_key_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventKeyList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def event_key_list_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List event keys
+
+        Lists all event keys for a tenant.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_key_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventKeyList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _event_key_list_serialize(
+        self,
+        tenant,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/events/keys",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def event_list(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        keys: Annotated[
+            Optional[List[StrictStr]], Field(description="A list of keys to filter by")
+        ] = None,
+        workflows: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of workflow IDs to filter by"),
+        ] = None,
+        statuses: Annotated[
+            Optional[List[WorkflowRunStatus]],
+            Field(description="A list of workflow run statuses to filter by"),
+        ] = None,
+        search: Annotated[
+            Optional[StrictStr], Field(description="The search query to filter for")
+        ] = None,
+        order_by_field: Annotated[
+            Optional[EventOrderByField], Field(description="What to order by")
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[EventOrderByDirection], Field(description="The order direction")
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        event_ids: Annotated[
+            Optional[
+                List[Annotated[str, Field(min_length=36, strict=True, max_length=36)]]
+            ],
+            Field(description="A list of event ids to filter by"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> EventList:
+        """List events
+
+        Lists all events for a tenant.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param keys: A list of keys to filter by
+        :type keys: List[str]
+        :param workflows: A list of workflow IDs to filter by
+        :type workflows: List[str]
+        :param statuses: A list of workflow run statuses to filter by
+        :type statuses: List[WorkflowRunStatus]
+        :param search: The search query to filter for
+        :type search: str
+        :param order_by_field: What to order by
+        :type order_by_field: EventOrderByField
+        :param order_by_direction: The order direction
+        :type order_by_direction: EventOrderByDirection
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :param event_ids: A list of event ids to filter by
+        :type event_ids: List[str]
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            keys=keys,
+            workflows=workflows,
+            statuses=statuses,
+            search=search,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            additional_metadata=additional_metadata,
+            event_ids=event_ids,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def event_list_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        keys: Annotated[
+            Optional[List[StrictStr]], Field(description="A list of keys to filter by")
+        ] = None,
+        workflows: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of workflow IDs to filter by"),
+        ] = None,
+        statuses: Annotated[
+            Optional[List[WorkflowRunStatus]],
+            Field(description="A list of workflow run statuses to filter by"),
+        ] = None,
+        search: Annotated[
+            Optional[StrictStr], Field(description="The search query to filter for")
+        ] = None,
+        order_by_field: Annotated[
+            Optional[EventOrderByField], Field(description="What to order by")
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[EventOrderByDirection], Field(description="The order direction")
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        event_ids: Annotated[
+            Optional[
+                List[Annotated[str, Field(min_length=36, strict=True, max_length=36)]]
+            ],
+            Field(description="A list of event ids to filter by"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[EventList]:
+        """List events
+
+        Lists all events for a tenant.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param keys: A list of keys to filter by
+        :type keys: List[str]
+        :param workflows: A list of workflow IDs to filter by
+        :type workflows: List[str]
+        :param statuses: A list of workflow run statuses to filter by
+        :type statuses: List[WorkflowRunStatus]
+        :param search: The search query to filter for
+        :type search: str
+        :param order_by_field: What to order by
+        :type order_by_field: EventOrderByField
+        :param order_by_direction: The order direction
+        :type order_by_direction: EventOrderByDirection
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :param event_ids: A list of event ids to filter by
+        :type event_ids: List[str]
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            keys=keys,
+            workflows=workflows,
+            statuses=statuses,
+            search=search,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            additional_metadata=additional_metadata,
+            event_ids=event_ids,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def event_list_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        keys: Annotated[
+            Optional[List[StrictStr]], Field(description="A list of keys to filter by")
+        ] = None,
+        workflows: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of workflow IDs to filter by"),
+        ] = None,
+        statuses: Annotated[
+            Optional[List[WorkflowRunStatus]],
+            Field(description="A list of workflow run statuses to filter by"),
+        ] = None,
+        search: Annotated[
+            Optional[StrictStr], Field(description="The search query to filter for")
+        ] = None,
+        order_by_field: Annotated[
+            Optional[EventOrderByField], Field(description="What to order by")
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[EventOrderByDirection], Field(description="The order direction")
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        event_ids: Annotated[
+            Optional[
+                List[Annotated[str, Field(min_length=36, strict=True, max_length=36)]]
+            ],
+            Field(description="A list of event ids to filter by"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List events
+
+        Lists all events for a tenant.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param keys: A list of keys to filter by
+        :type keys: List[str]
+        :param workflows: A list of workflow IDs to filter by
+        :type workflows: List[str]
+        :param statuses: A list of workflow run statuses to filter by
+        :type statuses: List[WorkflowRunStatus]
+        :param search: The search query to filter for
+        :type search: str
+        :param order_by_field: What to order by
+        :type order_by_field: EventOrderByField
+        :param order_by_direction: The order direction
+        :type order_by_direction: EventOrderByDirection
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :param event_ids: A list of event ids to filter by
+        :type event_ids: List[str]
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            keys=keys,
+            workflows=workflows,
+            statuses=statuses,
+            search=search,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            additional_metadata=additional_metadata,
+            event_ids=event_ids,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _event_list_serialize(
+        self,
+        tenant,
+        offset,
+        limit,
+        keys,
+        workflows,
+        statuses,
+        search,
+        order_by_field,
+        order_by_direction,
+        additional_metadata,
+        event_ids,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {
+            "keys": "multi",
+            "workflows": "multi",
+            "statuses": "multi",
+            "additionalMetadata": "multi",
+            "eventIds": "multi",
+        }
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        if offset is not None:
+
+            _query_params.append(("offset", offset))
+
+        if limit is not None:
+
+            _query_params.append(("limit", limit))
+
+        if keys is not None:
+
+            _query_params.append(("keys", keys))
+
+        if workflows is not None:
+
+            _query_params.append(("workflows", workflows))
+
+        if statuses is not None:
+
+            _query_params.append(("statuses", statuses))
+
+        if search is not None:
+
+            _query_params.append(("search", search))
+
+        if order_by_field is not None:
+
+            _query_params.append(("orderByField", order_by_field.value))
+
+        if order_by_direction is not None:
+
+            _query_params.append(("orderByDirection", order_by_direction.value))
+
+        if additional_metadata is not None:
+
+            _query_params.append(("additionalMetadata", additional_metadata))
+
+        if event_ids is not None:
+
+            _query_params.append(("eventIds", event_ids))
+
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/events",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def event_update_cancel(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        cancel_event_request: Annotated[
+            CancelEventRequest, Field(description="The event ids to replay")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> EventUpdateCancel200Response:
+        """Replay events
+
+        Cancels all runs for a list of events.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param cancel_event_request: The event ids to replay (required)
+        :type cancel_event_request: CancelEventRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_update_cancel_serialize(
+            tenant=tenant,
+            cancel_event_request=cancel_event_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventUpdateCancel200Response",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def event_update_cancel_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        cancel_event_request: Annotated[
+            CancelEventRequest, Field(description="The event ids to replay")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[EventUpdateCancel200Response]:
+        """Replay events
+
+        Cancels all runs for a list of events.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param cancel_event_request: The event ids to replay (required)
+        :type cancel_event_request: CancelEventRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_update_cancel_serialize(
+            tenant=tenant,
+            cancel_event_request=cancel_event_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventUpdateCancel200Response",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def event_update_cancel_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        cancel_event_request: Annotated[
+            CancelEventRequest, Field(description="The event ids to replay")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Replay events
+
+        Cancels all runs for a list of events.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param cancel_event_request: The event ids to replay (required)
+        :type cancel_event_request: CancelEventRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_update_cancel_serialize(
+            tenant=tenant,
+            cancel_event_request=cancel_event_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventUpdateCancel200Response",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _event_update_cancel_serialize(
+        self,
+        tenant,
+        cancel_event_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if cancel_event_request is not None:
+            _body_params = cancel_event_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants/{tenant}/events/cancel",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def event_update_replay(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        replay_event_request: Annotated[
+            ReplayEventRequest, Field(description="The event ids to replay")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> EventList:
+        """Replay events
+
+        Replays a list of events.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param replay_event_request: The event ids to replay (required)
+        :type replay_event_request: ReplayEventRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_update_replay_serialize(
+            tenant=tenant,
+            replay_event_request=replay_event_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def event_update_replay_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        replay_event_request: Annotated[
+            ReplayEventRequest, Field(description="The event ids to replay")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[EventList]:
+        """Replay events
+
+        Replays a list of events.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param replay_event_request: The event ids to replay (required)
+        :type replay_event_request: ReplayEventRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_update_replay_serialize(
+            tenant=tenant,
+            replay_event_request=replay_event_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def event_update_replay_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        replay_event_request: Annotated[
+            ReplayEventRequest, Field(description="The event ids to replay")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Replay events
+
+        Replays a list of events.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param replay_event_request: The event ids to replay (required)
+        :type replay_event_request: ReplayEventRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._event_update_replay_serialize(
+            tenant=tenant,
+            replay_event_request=replay_event_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _event_update_replay_serialize(
+        self,
+        tenant,
+        replay_event_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if replay_event_request is not None:
+            _body_params = replay_event_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants/{tenant}/events/replay",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/github_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/github_api.py
new file mode 100644
index 00000000..23c1b269
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/github_api.py
@@ -0,0 +1,331 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class GithubApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def sns_update(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        event: Annotated[
+            str,
+            Field(
+                min_length=1, strict=True, max_length=255, description="The event key"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Github app tenant webhook
+
+        SNS event
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param event: The event key (required)
+        :type event: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._sns_update_serialize(
+            tenant=tenant,
+            event=event,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def sns_update_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        event: Annotated[
+            str,
+            Field(
+                min_length=1, strict=True, max_length=255, description="The event key"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Github app tenant webhook
+
+        SNS event
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param event: The event key (required)
+        :type event: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._sns_update_serialize(
+            tenant=tenant,
+            event=event,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def sns_update_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        event: Annotated[
+            str,
+            Field(
+                min_length=1, strict=True, max_length=255, description="The event key"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Github app tenant webhook
+
+        SNS event
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param event: The event key (required)
+        :type event: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._sns_update_serialize(
+            tenant=tenant,
+            event=event,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _sns_update_serialize(
+        self,
+        tenant,
+        event,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if event is not None:
+            _path_params["event"] = event
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = []
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/sns/{tenant}/{event}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/healthcheck_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/healthcheck_api.py
new file mode 100644
index 00000000..4b7793eb
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/healthcheck_api.py
@@ -0,0 +1,483 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class HealthcheckApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def liveness_get(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Get liveness
+
+        Gets the liveness status
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._liveness_get_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "500": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def liveness_get_with_http_info(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Get liveness
+
+        Gets the liveness status
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._liveness_get_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "500": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def liveness_get_without_preload_content(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get liveness
+
+        Gets the liveness status
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._liveness_get_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "500": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _liveness_get_serialize(
+        self,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # authentication setting
+        _auth_settings: List[str] = []
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/live",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def readiness_get(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Get readiness
+
+        Gets the readiness status
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._readiness_get_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "500": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def readiness_get_with_http_info(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Get readiness
+
+        Gets the readiness status
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._readiness_get_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "500": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def readiness_get_without_preload_content(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get readiness
+
+        Gets the readiness status
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._readiness_get_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "500": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _readiness_get_serialize(
+        self,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # authentication setting
+        _auth_settings: List[str] = []
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/ready",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/log_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/log_api.py
new file mode 100644
index 00000000..eaf16677
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/log_api.py
@@ -0,0 +1,447 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.models.log_line_level import LogLineLevel
+from hatchet_sdk.clients.rest.models.log_line_list import LogLineList
+from hatchet_sdk.clients.rest.models.log_line_order_by_direction import (
+    LogLineOrderByDirection,
+)
+from hatchet_sdk.clients.rest.models.log_line_order_by_field import LogLineOrderByField
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class LogApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def log_line_list(
+        self,
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        levels: Annotated[
+            Optional[List[LogLineLevel]],
+            Field(description="A list of levels to filter by"),
+        ] = None,
+        search: Annotated[
+            Optional[StrictStr], Field(description="The search query to filter for")
+        ] = None,
+        order_by_field: Annotated[
+            Optional[LogLineOrderByField], Field(description="What to order by")
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[LogLineOrderByDirection], Field(description="The order direction")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> LogLineList:
+        """List log lines
+
+        Lists log lines for a step run.
+
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param levels: A list of levels to filter by
+        :type levels: List[LogLineLevel]
+        :param search: The search query to filter for
+        :type search: str
+        :param order_by_field: What to order by
+        :type order_by_field: LogLineOrderByField
+        :param order_by_direction: The order direction
+        :type order_by_direction: LogLineOrderByDirection
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._log_line_list_serialize(
+            step_run=step_run,
+            offset=offset,
+            limit=limit,
+            levels=levels,
+            search=search,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "LogLineList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def log_line_list_with_http_info(
+        self,
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        levels: Annotated[
+            Optional[List[LogLineLevel]],
+            Field(description="A list of levels to filter by"),
+        ] = None,
+        search: Annotated[
+            Optional[StrictStr], Field(description="The search query to filter for")
+        ] = None,
+        order_by_field: Annotated[
+            Optional[LogLineOrderByField], Field(description="What to order by")
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[LogLineOrderByDirection], Field(description="The order direction")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[LogLineList]:
+        """List log lines
+
+        Lists log lines for a step run.
+
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param levels: A list of levels to filter by
+        :type levels: List[LogLineLevel]
+        :param search: The search query to filter for
+        :type search: str
+        :param order_by_field: What to order by
+        :type order_by_field: LogLineOrderByField
+        :param order_by_direction: The order direction
+        :type order_by_direction: LogLineOrderByDirection
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._log_line_list_serialize(
+            step_run=step_run,
+            offset=offset,
+            limit=limit,
+            levels=levels,
+            search=search,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "LogLineList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def log_line_list_without_preload_content(
+        self,
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        levels: Annotated[
+            Optional[List[LogLineLevel]],
+            Field(description="A list of levels to filter by"),
+        ] = None,
+        search: Annotated[
+            Optional[StrictStr], Field(description="The search query to filter for")
+        ] = None,
+        order_by_field: Annotated[
+            Optional[LogLineOrderByField], Field(description="What to order by")
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[LogLineOrderByDirection], Field(description="The order direction")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List log lines
+
+        Lists log lines for a step run.
+
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param levels: A list of levels to filter by
+        :type levels: List[LogLineLevel]
+        :param search: The search query to filter for
+        :type search: str
+        :param order_by_field: What to order by
+        :type order_by_field: LogLineOrderByField
+        :param order_by_direction: The order direction
+        :type order_by_direction: LogLineOrderByDirection
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._log_line_list_serialize(
+            step_run=step_run,
+            offset=offset,
+            limit=limit,
+            levels=levels,
+            search=search,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "LogLineList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _log_line_list_serialize(
+        self,
+        step_run,
+        offset,
+        limit,
+        levels,
+        search,
+        order_by_field,
+        order_by_direction,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {
+            "levels": "multi",
+        }
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if step_run is not None:
+            _path_params["step-run"] = step_run
+        # process the query parameters
+        if offset is not None:
+
+            _query_params.append(("offset", offset))
+
+        if limit is not None:
+
+            _query_params.append(("limit", limit))
+
+        if levels is not None:
+
+            _query_params.append(("levels", levels))
+
+        if search is not None:
+
+            _query_params.append(("search", search))
+
+        if order_by_field is not None:
+
+            _query_params.append(("orderByField", order_by_field.value))
+
+        if order_by_direction is not None:
+
+            _query_params.append(("orderByDirection", order_by_direction.value))
+
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/step-runs/{step-run}/logs",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/metadata_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/metadata_api.py
new file mode 100644
index 00000000..61659069
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/metadata_api.py
@@ -0,0 +1,728 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.models.api_errors import APIErrors
+from hatchet_sdk.clients.rest.models.api_meta import APIMeta
+from hatchet_sdk.clients.rest.models.api_meta_integration import APIMetaIntegration
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class MetadataApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def cloud_metadata_get(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> APIErrors:
+        """Get cloud metadata
+
+        Gets metadata for the Hatchet cloud instance
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._cloud_metadata_get_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "APIErrors",
+            "400": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def cloud_metadata_get_with_http_info(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[APIErrors]:
+        """Get cloud metadata
+
+        Gets metadata for the Hatchet cloud instance
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._cloud_metadata_get_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "APIErrors",
+            "400": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def cloud_metadata_get_without_preload_content(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get cloud metadata
+
+        Gets metadata for the Hatchet cloud instance
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._cloud_metadata_get_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "APIErrors",
+            "400": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _cloud_metadata_get_serialize(
+        self,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = []
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/cloud/metadata",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def metadata_get(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> APIMeta:
+        """Get metadata
+
+        Gets metadata for the Hatchet instance
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._metadata_get_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "APIMeta",
+            "400": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def metadata_get_with_http_info(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[APIMeta]:
+        """Get metadata
+
+        Gets metadata for the Hatchet instance
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._metadata_get_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "APIMeta",
+            "400": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def metadata_get_without_preload_content(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get metadata
+
+        Gets metadata for the Hatchet instance
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._metadata_get_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "APIMeta",
+            "400": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _metadata_get_serialize(
+        self,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = []
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/meta",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def metadata_list_integrations(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> List[APIMetaIntegration]:
+        """List integrations
+
+        List all integrations
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._metadata_list_integrations_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "List[APIMetaIntegration]",
+            "400": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def metadata_list_integrations_with_http_info(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[List[APIMetaIntegration]]:
+        """List integrations
+
+        List all integrations
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._metadata_list_integrations_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "List[APIMetaIntegration]",
+            "400": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def metadata_list_integrations_without_preload_content(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List integrations
+
+        List all integrations
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._metadata_list_integrations_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "List[APIMetaIntegration]",
+            "400": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _metadata_list_integrations_serialize(
+        self,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/meta/integrations",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/rate_limits_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/rate_limits_api.py
new file mode 100644
index 00000000..c5e7e4ee
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/rate_limits_api.py
@@ -0,0 +1,423 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.models.rate_limit_list import RateLimitList
+from hatchet_sdk.clients.rest.models.rate_limit_order_by_direction import (
+    RateLimitOrderByDirection,
+)
+from hatchet_sdk.clients.rest.models.rate_limit_order_by_field import (
+    RateLimitOrderByField,
+)
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class RateLimitsApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def rate_limit_list(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        search: Annotated[
+            Optional[StrictStr], Field(description="The search query to filter for")
+        ] = None,
+        order_by_field: Annotated[
+            Optional[RateLimitOrderByField], Field(description="What to order by")
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[RateLimitOrderByDirection],
+            Field(description="The order direction"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RateLimitList:
+        """List rate limits
+
+        Lists all rate limits for a tenant.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param search: The search query to filter for
+        :type search: str
+        :param order_by_field: What to order by
+        :type order_by_field: RateLimitOrderByField
+        :param order_by_direction: The order direction
+        :type order_by_direction: RateLimitOrderByDirection
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._rate_limit_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            search=search,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "RateLimitList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def rate_limit_list_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        search: Annotated[
+            Optional[StrictStr], Field(description="The search query to filter for")
+        ] = None,
+        order_by_field: Annotated[
+            Optional[RateLimitOrderByField], Field(description="What to order by")
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[RateLimitOrderByDirection],
+            Field(description="The order direction"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[RateLimitList]:
+        """List rate limits
+
+        Lists all rate limits for a tenant.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param search: The search query to filter for
+        :type search: str
+        :param order_by_field: What to order by
+        :type order_by_field: RateLimitOrderByField
+        :param order_by_direction: The order direction
+        :type order_by_direction: RateLimitOrderByDirection
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._rate_limit_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            search=search,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "RateLimitList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def rate_limit_list_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        search: Annotated[
+            Optional[StrictStr], Field(description="The search query to filter for")
+        ] = None,
+        order_by_field: Annotated[
+            Optional[RateLimitOrderByField], Field(description="What to order by")
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[RateLimitOrderByDirection],
+            Field(description="The order direction"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List rate limits
+
+        Lists all rate limits for a tenant.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param search: The search query to filter for
+        :type search: str
+        :param order_by_field: What to order by
+        :type order_by_field: RateLimitOrderByField
+        :param order_by_direction: The order direction
+        :type order_by_direction: RateLimitOrderByDirection
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._rate_limit_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            search=search,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "RateLimitList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _rate_limit_list_serialize(
+        self,
+        tenant,
+        offset,
+        limit,
+        search,
+        order_by_field,
+        order_by_direction,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        if offset is not None:
+
+            _query_params.append(("offset", offset))
+
+        if limit is not None:
+
+            _query_params.append(("limit", limit))
+
+        if search is not None:
+
+            _query_params.append(("search", search))
+
+        if order_by_field is not None:
+
+            _query_params.append(("orderByField", order_by_field.value))
+
+        if order_by_direction is not None:
+
+            _query_params.append(("orderByDirection", order_by_direction.value))
+
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/rate-limits",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/slack_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/slack_api.py
new file mode 100644
index 00000000..9b0e637d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/slack_api.py
@@ -0,0 +1,577 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.models.list_slack_webhooks import ListSlackWebhooks
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class SlackApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def slack_webhook_delete(
+        self,
+        slack: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The Slack webhook id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Delete Slack webhook
+
+        Delete Slack webhook
+
+        :param slack: The Slack webhook id (required)
+        :type slack: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._slack_webhook_delete_serialize(
+            slack=slack,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def slack_webhook_delete_with_http_info(
+        self,
+        slack: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The Slack webhook id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Delete Slack webhook
+
+        Delete Slack webhook
+
+        :param slack: The Slack webhook id (required)
+        :type slack: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._slack_webhook_delete_serialize(
+            slack=slack,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def slack_webhook_delete_without_preload_content(
+        self,
+        slack: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The Slack webhook id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Delete Slack webhook
+
+        Delete Slack webhook
+
+        :param slack: The Slack webhook id (required)
+        :type slack: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._slack_webhook_delete_serialize(
+            slack=slack,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _slack_webhook_delete_serialize(
+        self,
+        slack,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if slack is not None:
+            _path_params["slack"] = slack
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="DELETE",
+            resource_path="/api/v1/slack/{slack}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def slack_webhook_list(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ListSlackWebhooks:
+        """List Slack integrations
+
+        List Slack webhooks
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._slack_webhook_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ListSlackWebhooks",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def slack_webhook_list_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[ListSlackWebhooks]:
+        """List Slack integrations
+
+        List Slack webhooks
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._slack_webhook_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ListSlackWebhooks",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def slack_webhook_list_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List Slack integrations
+
+        List Slack webhooks
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._slack_webhook_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ListSlackWebhooks",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _slack_webhook_list_serialize(
+        self,
+        tenant,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/slack",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/sns_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/sns_api.py
new file mode 100644
index 00000000..bb020ceb
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/sns_api.py
@@ -0,0 +1,872 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.models.create_sns_integration_request import (
+    CreateSNSIntegrationRequest,
+)
+from hatchet_sdk.clients.rest.models.list_sns_integrations import ListSNSIntegrations
+from hatchet_sdk.clients.rest.models.sns_integration import SNSIntegration
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class SNSApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def sns_create(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        create_sns_integration_request: Optional[CreateSNSIntegrationRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> SNSIntegration:
+        """Create SNS integration
+
+        Create SNS integration
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param create_sns_integration_request:
+        :type create_sns_integration_request: CreateSNSIntegrationRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._sns_create_serialize(
+            tenant=tenant,
+            create_sns_integration_request=create_sns_integration_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "201": "SNSIntegration",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def sns_create_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        create_sns_integration_request: Optional[CreateSNSIntegrationRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[SNSIntegration]:
+        """Create SNS integration
+
+        Create SNS integration
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param create_sns_integration_request:
+        :type create_sns_integration_request: CreateSNSIntegrationRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._sns_create_serialize(
+            tenant=tenant,
+            create_sns_integration_request=create_sns_integration_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "201": "SNSIntegration",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def sns_create_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        create_sns_integration_request: Optional[CreateSNSIntegrationRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Create SNS integration
+
+        Create SNS integration
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param create_sns_integration_request:
+        :type create_sns_integration_request: CreateSNSIntegrationRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._sns_create_serialize(
+            tenant=tenant,
+            create_sns_integration_request=create_sns_integration_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "201": "SNSIntegration",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _sns_create_serialize(
+        self,
+        tenant,
+        create_sns_integration_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if create_sns_integration_request is not None:
+            _body_params = create_sns_integration_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants/{tenant}/sns",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def sns_delete(
+        self,
+        sns: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The SNS integration id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Delete SNS integration
+
+        Delete SNS integration
+
+        :param sns: The SNS integration id (required)
+        :type sns: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._sns_delete_serialize(
+            sns=sns,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def sns_delete_with_http_info(
+        self,
+        sns: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The SNS integration id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Delete SNS integration
+
+        Delete SNS integration
+
+        :param sns: The SNS integration id (required)
+        :type sns: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._sns_delete_serialize(
+            sns=sns,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def sns_delete_without_preload_content(
+        self,
+        sns: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The SNS integration id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Delete SNS integration
+
+        Delete SNS integration
+
+        :param sns: The SNS integration id (required)
+        :type sns: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._sns_delete_serialize(
+            sns=sns,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _sns_delete_serialize(
+        self,
+        sns,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if sns is not None:
+            _path_params["sns"] = sns
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="DELETE",
+            resource_path="/api/v1/sns/{sns}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def sns_list(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ListSNSIntegrations:
+        """List SNS integrations
+
+        List SNS integrations
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._sns_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ListSNSIntegrations",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def sns_list_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[ListSNSIntegrations]:
+        """List SNS integrations
+
+        List SNS integrations
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._sns_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ListSNSIntegrations",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def sns_list_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List SNS integrations
+
+        List SNS integrations
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._sns_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ListSNSIntegrations",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _sns_list_serialize(
+        self,
+        tenant,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/sns",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/step_run_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/step_run_api.py
new file mode 100644
index 00000000..851ed174
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/step_run_api.py
@@ -0,0 +1,2200 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.models.rerun_step_run_request import RerunStepRunRequest
+from hatchet_sdk.clients.rest.models.step_run import StepRun
+from hatchet_sdk.clients.rest.models.step_run_archive_list import StepRunArchiveList
+from hatchet_sdk.clients.rest.models.step_run_event_list import StepRunEventList
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class StepRunApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def step_run_get(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> StepRun:
+        """Get step run
+
+        Get a step run by id
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_get_serialize(
+            tenant=tenant,
+            step_run=step_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRun",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def step_run_get_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[StepRun]:
+        """Get step run
+
+        Get a step run by id
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_get_serialize(
+            tenant=tenant,
+            step_run=step_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRun",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def step_run_get_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get step run
+
+        Get a step run by id
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_get_serialize(
+            tenant=tenant,
+            step_run=step_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRun",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _step_run_get_serialize(
+        self,
+        tenant,
+        step_run,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if step_run is not None:
+            _path_params["step-run"] = step_run
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/step-runs/{step-run}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def step_run_get_schema(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> object:
+        """Get step run schema
+
+        Get the schema for a step run
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_get_schema_serialize(
+            tenant=tenant,
+            step_run=step_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "object",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def step_run_get_schema_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[object]:
+        """Get step run schema
+
+        Get the schema for a step run
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_get_schema_serialize(
+            tenant=tenant,
+            step_run=step_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "object",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def step_run_get_schema_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get step run schema
+
+        Get the schema for a step run
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_get_schema_serialize(
+            tenant=tenant,
+            step_run=step_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "object",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _step_run_get_schema_serialize(
+        self,
+        tenant,
+        step_run,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if step_run is not None:
+            _path_params["step-run"] = step_run
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/step-runs/{step-run}/schema",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def step_run_list_archives(
+        self,
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> StepRunArchiveList:
+        """List archives for step run
+
+        List archives for a step run
+
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_list_archives_serialize(
+            step_run=step_run,
+            offset=offset,
+            limit=limit,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRunArchiveList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def step_run_list_archives_with_http_info(
+        self,
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[StepRunArchiveList]:
+        """List archives for step run
+
+        List archives for a step run
+
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_list_archives_serialize(
+            step_run=step_run,
+            offset=offset,
+            limit=limit,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRunArchiveList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def step_run_list_archives_without_preload_content(
+        self,
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List archives for step run
+
+        List archives for a step run
+
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_list_archives_serialize(
+            step_run=step_run,
+            offset=offset,
+            limit=limit,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRunArchiveList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _step_run_list_archives_serialize(
+        self,
+        step_run,
+        offset,
+        limit,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if step_run is not None:
+            _path_params["step-run"] = step_run
+        # process the query parameters
+        if offset is not None:
+
+            _query_params.append(("offset", offset))
+
+        if limit is not None:
+
+            _query_params.append(("limit", limit))
+
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/step-runs/{step-run}/archives",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def step_run_list_events(
+        self,
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> StepRunEventList:
+        """List events for step run
+
+        List events for a step run
+
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_list_events_serialize(
+            step_run=step_run,
+            offset=offset,
+            limit=limit,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRunEventList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def step_run_list_events_with_http_info(
+        self,
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[StepRunEventList]:
+        """List events for step run
+
+        List events for a step run
+
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_list_events_serialize(
+            step_run=step_run,
+            offset=offset,
+            limit=limit,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRunEventList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def step_run_list_events_without_preload_content(
+        self,
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List events for step run
+
+        List events for a step run
+
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_list_events_serialize(
+            step_run=step_run,
+            offset=offset,
+            limit=limit,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRunEventList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _step_run_list_events_serialize(
+        self,
+        step_run,
+        offset,
+        limit,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if step_run is not None:
+            _path_params["step-run"] = step_run
+        # process the query parameters
+        if offset is not None:
+
+            _query_params.append(("offset", offset))
+
+        if limit is not None:
+
+            _query_params.append(("limit", limit))
+
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/step-runs/{step-run}/events",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def step_run_update_cancel(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> StepRun:
+        """Attempts to cancel a step run
+
+        Attempts to cancel a step run
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_update_cancel_serialize(
+            tenant=tenant,
+            step_run=step_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRun",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def step_run_update_cancel_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[StepRun]:
+        """Attempts to cancel a step run
+
+        Attempts to cancel a step run
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_update_cancel_serialize(
+            tenant=tenant,
+            step_run=step_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRun",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def step_run_update_cancel_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Attempts to cancel a step run
+
+        Attempts to cancel a step run
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_update_cancel_serialize(
+            tenant=tenant,
+            step_run=step_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRun",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _step_run_update_cancel_serialize(
+        self,
+        tenant,
+        step_run,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if step_run is not None:
+            _path_params["step-run"] = step_run
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants/{tenant}/step-runs/{step-run}/cancel",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def step_run_update_rerun(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        rerun_step_run_request: Annotated[
+            RerunStepRunRequest, Field(description="The input to the rerun")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> StepRun:
+        """Rerun step run
+
+        Reruns a step run
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :param rerun_step_run_request: The input to the rerun (required)
+        :type rerun_step_run_request: RerunStepRunRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_update_rerun_serialize(
+            tenant=tenant,
+            step_run=step_run,
+            rerun_step_run_request=rerun_step_run_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRun",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def step_run_update_rerun_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        rerun_step_run_request: Annotated[
+            RerunStepRunRequest, Field(description="The input to the rerun")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[StepRun]:
+        """Rerun step run
+
+        Reruns a step run
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :param rerun_step_run_request: The input to the rerun (required)
+        :type rerun_step_run_request: RerunStepRunRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_update_rerun_serialize(
+            tenant=tenant,
+            step_run=step_run,
+            rerun_step_run_request=rerun_step_run_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRun",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def step_run_update_rerun_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        step_run: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The step run id"
+            ),
+        ],
+        rerun_step_run_request: Annotated[
+            RerunStepRunRequest, Field(description="The input to the rerun")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Rerun step run
+
+        Reruns a step run
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param step_run: The step run id (required)
+        :type step_run: str
+        :param rerun_step_run_request: The input to the rerun (required)
+        :type rerun_step_run_request: RerunStepRunRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._step_run_update_rerun_serialize(
+            tenant=tenant,
+            step_run=step_run,
+            rerun_step_run_request=rerun_step_run_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRun",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _step_run_update_rerun_serialize(
+        self,
+        tenant,
+        step_run,
+        rerun_step_run_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if step_run is not None:
+            _path_params["step-run"] = step_run
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if rerun_step_run_request is not None:
+            _body_params = rerun_step_run_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants/{tenant}/step-runs/{step-run}/rerun",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_run_list_step_run_events(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The workflow run id",
+            ),
+        ],
+        last_id: Annotated[
+            Optional[StrictInt], Field(description="Last ID of the last event")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> StepRunEventList:
+        """List events for all step runs for a workflow run
+
+        List events for all step runs for a workflow run
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow_run: The workflow run id (required)
+        :type workflow_run: str
+        :param last_id: Last ID of the last event
+        :type last_id: int
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_list_step_run_events_serialize(
+            tenant=tenant,
+            workflow_run=workflow_run,
+            last_id=last_id,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRunEventList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_run_list_step_run_events_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The workflow run id",
+            ),
+        ],
+        last_id: Annotated[
+            Optional[StrictInt], Field(description="Last ID of the last event")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[StepRunEventList]:
+        """List events for all step runs for a workflow run
+
+        List events for all step runs for a workflow run
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow_run: The workflow run id (required)
+        :type workflow_run: str
+        :param last_id: Last ID of the last event
+        :type last_id: int
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_list_step_run_events_serialize(
+            tenant=tenant,
+            workflow_run=workflow_run,
+            last_id=last_id,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRunEventList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_run_list_step_run_events_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The workflow run id",
+            ),
+        ],
+        last_id: Annotated[
+            Optional[StrictInt], Field(description="Last ID of the last event")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List events for all step runs for a workflow run
+
+        List events for all step runs for a workflow run
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow_run: The workflow run id (required)
+        :type workflow_run: str
+        :param last_id: Last ID of the last event
+        :type last_id: int
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_list_step_run_events_serialize(
+            tenant=tenant,
+            workflow_run=workflow_run,
+            last_id=last_id,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "StepRunEventList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_run_list_step_run_events_serialize(
+        self,
+        tenant,
+        workflow_run,
+        last_id,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if workflow_run is not None:
+            _path_params["workflow-run"] = workflow_run
+        # process the query parameters
+        if last_id is not None:
+
+            _query_params.append(("lastId", last_id))
+
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/workflow-runs/{workflow-run}/step-run-events",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/tenant_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/tenant_api.py
new file mode 100644
index 00000000..cd5e4f07
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/tenant_api.py
@@ -0,0 +1,4428 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.models.accept_invite_request import AcceptInviteRequest
+from hatchet_sdk.clients.rest.models.create_tenant_alert_email_group_request import (
+    CreateTenantAlertEmailGroupRequest,
+)
+from hatchet_sdk.clients.rest.models.create_tenant_invite_request import (
+    CreateTenantInviteRequest,
+)
+from hatchet_sdk.clients.rest.models.create_tenant_request import CreateTenantRequest
+from hatchet_sdk.clients.rest.models.reject_invite_request import RejectInviteRequest
+from hatchet_sdk.clients.rest.models.tenant import Tenant
+from hatchet_sdk.clients.rest.models.tenant_alert_email_group import (
+    TenantAlertEmailGroup,
+)
+from hatchet_sdk.clients.rest.models.tenant_alert_email_group_list import (
+    TenantAlertEmailGroupList,
+)
+from hatchet_sdk.clients.rest.models.tenant_alerting_settings import (
+    TenantAlertingSettings,
+)
+from hatchet_sdk.clients.rest.models.tenant_invite import TenantInvite
+from hatchet_sdk.clients.rest.models.tenant_invite_list import TenantInviteList
+from hatchet_sdk.clients.rest.models.tenant_member import TenantMember
+from hatchet_sdk.clients.rest.models.tenant_member_list import TenantMemberList
+from hatchet_sdk.clients.rest.models.tenant_resource_policy import TenantResourcePolicy
+from hatchet_sdk.clients.rest.models.tenant_step_run_queue_metrics import (
+    TenantStepRunQueueMetrics,
+)
+from hatchet_sdk.clients.rest.models.update_tenant_alert_email_group_request import (
+    UpdateTenantAlertEmailGroupRequest,
+)
+from hatchet_sdk.clients.rest.models.update_tenant_request import UpdateTenantRequest
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class TenantApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def alert_email_group_create(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        create_tenant_alert_email_group_request: Annotated[
+            CreateTenantAlertEmailGroupRequest,
+            Field(description="The tenant alert email group to create"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> TenantAlertEmailGroup:
+        """Create tenant alert email group
+
+        Creates a new tenant alert email group
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param create_tenant_alert_email_group_request: The tenant alert email group to create (required)
+        :type create_tenant_alert_email_group_request: CreateTenantAlertEmailGroupRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._alert_email_group_create_serialize(
+            tenant=tenant,
+            create_tenant_alert_email_group_request=create_tenant_alert_email_group_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "201": "TenantAlertEmailGroup",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def alert_email_group_create_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        create_tenant_alert_email_group_request: Annotated[
+            CreateTenantAlertEmailGroupRequest,
+            Field(description="The tenant alert email group to create"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[TenantAlertEmailGroup]:
+        """Create tenant alert email group
+
+        Creates a new tenant alert email group
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param create_tenant_alert_email_group_request: The tenant alert email group to create (required)
+        :type create_tenant_alert_email_group_request: CreateTenantAlertEmailGroupRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._alert_email_group_create_serialize(
+            tenant=tenant,
+            create_tenant_alert_email_group_request=create_tenant_alert_email_group_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "201": "TenantAlertEmailGroup",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def alert_email_group_create_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        create_tenant_alert_email_group_request: Annotated[
+            CreateTenantAlertEmailGroupRequest,
+            Field(description="The tenant alert email group to create"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Create tenant alert email group
+
+        Creates a new tenant alert email group
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param create_tenant_alert_email_group_request: The tenant alert email group to create (required)
+        :type create_tenant_alert_email_group_request: CreateTenantAlertEmailGroupRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._alert_email_group_create_serialize(
+            tenant=tenant,
+            create_tenant_alert_email_group_request=create_tenant_alert_email_group_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "201": "TenantAlertEmailGroup",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _alert_email_group_create_serialize(
+        self,
+        tenant,
+        create_tenant_alert_email_group_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if create_tenant_alert_email_group_request is not None:
+            _body_params = create_tenant_alert_email_group_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants/{tenant}/alerting-email-groups",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def alert_email_group_delete(
+        self,
+        alert_email_group: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The tenant alert email group id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Delete tenant alert email group
+
+        Deletes a tenant alert email group
+
+        :param alert_email_group: The tenant alert email group id (required)
+        :type alert_email_group: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._alert_email_group_delete_serialize(
+            alert_email_group=alert_email_group,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def alert_email_group_delete_with_http_info(
+        self,
+        alert_email_group: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The tenant alert email group id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Delete tenant alert email group
+
+        Deletes a tenant alert email group
+
+        :param alert_email_group: The tenant alert email group id (required)
+        :type alert_email_group: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._alert_email_group_delete_serialize(
+            alert_email_group=alert_email_group,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def alert_email_group_delete_without_preload_content(
+        self,
+        alert_email_group: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The tenant alert email group id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Delete tenant alert email group
+
+        Deletes a tenant alert email group
+
+        :param alert_email_group: The tenant alert email group id (required)
+        :type alert_email_group: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._alert_email_group_delete_serialize(
+            alert_email_group=alert_email_group,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _alert_email_group_delete_serialize(
+        self,
+        alert_email_group,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if alert_email_group is not None:
+            _path_params["alert-email-group"] = alert_email_group
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="DELETE",
+            resource_path="/api/v1/alerting-email-groups/{alert-email-group}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def alert_email_group_list(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> TenantAlertEmailGroupList:
+        """List tenant alert email groups
+
+        Gets a list of tenant alert email groups
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._alert_email_group_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantAlertEmailGroupList",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def alert_email_group_list_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[TenantAlertEmailGroupList]:
+        """List tenant alert email groups
+
+        Gets a list of tenant alert email groups
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._alert_email_group_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantAlertEmailGroupList",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def alert_email_group_list_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List tenant alert email groups
+
+        Gets a list of tenant alert email groups
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._alert_email_group_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantAlertEmailGroupList",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _alert_email_group_list_serialize(
+        self,
+        tenant,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/alerting-email-groups",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def alert_email_group_update(
+        self,
+        alert_email_group: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The tenant alert email group id",
+            ),
+        ],
+        update_tenant_alert_email_group_request: Annotated[
+            UpdateTenantAlertEmailGroupRequest,
+            Field(description="The tenant alert email group to update"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> TenantAlertEmailGroup:
+        """Update tenant alert email group
+
+        Updates a tenant alert email group
+
+        :param alert_email_group: The tenant alert email group id (required)
+        :type alert_email_group: str
+        :param update_tenant_alert_email_group_request: The tenant alert email group to update (required)
+        :type update_tenant_alert_email_group_request: UpdateTenantAlertEmailGroupRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._alert_email_group_update_serialize(
+            alert_email_group=alert_email_group,
+            update_tenant_alert_email_group_request=update_tenant_alert_email_group_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantAlertEmailGroup",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def alert_email_group_update_with_http_info(
+        self,
+        alert_email_group: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The tenant alert email group id",
+            ),
+        ],
+        update_tenant_alert_email_group_request: Annotated[
+            UpdateTenantAlertEmailGroupRequest,
+            Field(description="The tenant alert email group to update"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[TenantAlertEmailGroup]:
+        """Update tenant alert email group
+
+        Updates a tenant alert email group
+
+        :param alert_email_group: The tenant alert email group id (required)
+        :type alert_email_group: str
+        :param update_tenant_alert_email_group_request: The tenant alert email group to update (required)
+        :type update_tenant_alert_email_group_request: UpdateTenantAlertEmailGroupRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._alert_email_group_update_serialize(
+            alert_email_group=alert_email_group,
+            update_tenant_alert_email_group_request=update_tenant_alert_email_group_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantAlertEmailGroup",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def alert_email_group_update_without_preload_content(
+        self,
+        alert_email_group: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The tenant alert email group id",
+            ),
+        ],
+        update_tenant_alert_email_group_request: Annotated[
+            UpdateTenantAlertEmailGroupRequest,
+            Field(description="The tenant alert email group to update"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Update tenant alert email group
+
+        Updates a tenant alert email group
+
+        :param alert_email_group: The tenant alert email group id (required)
+        :type alert_email_group: str
+        :param update_tenant_alert_email_group_request: The tenant alert email group to update (required)
+        :type update_tenant_alert_email_group_request: UpdateTenantAlertEmailGroupRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._alert_email_group_update_serialize(
+            alert_email_group=alert_email_group,
+            update_tenant_alert_email_group_request=update_tenant_alert_email_group_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantAlertEmailGroup",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _alert_email_group_update_serialize(
+        self,
+        alert_email_group,
+        update_tenant_alert_email_group_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if alert_email_group is not None:
+            _path_params["alert-email-group"] = alert_email_group
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if update_tenant_alert_email_group_request is not None:
+            _body_params = update_tenant_alert_email_group_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="PATCH",
+            resource_path="/api/v1/alerting-email-groups/{alert-email-group}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def tenant_alerting_settings_get(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> TenantAlertingSettings:
+        """Get tenant alerting settings
+
+        Gets the alerting settings for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_alerting_settings_get_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantAlertingSettings",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def tenant_alerting_settings_get_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[TenantAlertingSettings]:
+        """Get tenant alerting settings
+
+        Gets the alerting settings for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_alerting_settings_get_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantAlertingSettings",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def tenant_alerting_settings_get_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get tenant alerting settings
+
+        Gets the alerting settings for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_alerting_settings_get_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantAlertingSettings",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _tenant_alerting_settings_get_serialize(
+        self,
+        tenant,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/alerting/settings",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def tenant_create(
+        self,
+        create_tenant_request: Annotated[
+            CreateTenantRequest, Field(description="The tenant to create")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> Tenant:
+        """Create tenant
+
+        Creates a new tenant
+
+        :param create_tenant_request: The tenant to create (required)
+        :type create_tenant_request: CreateTenantRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_create_serialize(
+            create_tenant_request=create_tenant_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Tenant",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def tenant_create_with_http_info(
+        self,
+        create_tenant_request: Annotated[
+            CreateTenantRequest, Field(description="The tenant to create")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[Tenant]:
+        """Create tenant
+
+        Creates a new tenant
+
+        :param create_tenant_request: The tenant to create (required)
+        :type create_tenant_request: CreateTenantRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_create_serialize(
+            create_tenant_request=create_tenant_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Tenant",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def tenant_create_without_preload_content(
+        self,
+        create_tenant_request: Annotated[
+            CreateTenantRequest, Field(description="The tenant to create")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Create tenant
+
+        Creates a new tenant
+
+        :param create_tenant_request: The tenant to create (required)
+        :type create_tenant_request: CreateTenantRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_create_serialize(
+            create_tenant_request=create_tenant_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Tenant",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _tenant_create_serialize(
+        self,
+        create_tenant_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if create_tenant_request is not None:
+            _body_params = create_tenant_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def tenant_get_step_run_queue_metrics(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> TenantStepRunQueueMetrics:
+        """Get step run metrics
+
+        Get the queue metrics for the tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_get_step_run_queue_metrics_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantStepRunQueueMetrics",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def tenant_get_step_run_queue_metrics_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[TenantStepRunQueueMetrics]:
+        """Get step run metrics
+
+        Get the queue metrics for the tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_get_step_run_queue_metrics_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantStepRunQueueMetrics",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def tenant_get_step_run_queue_metrics_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get step run metrics
+
+        Get the queue metrics for the tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_get_step_run_queue_metrics_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantStepRunQueueMetrics",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _tenant_get_step_run_queue_metrics_serialize(
+        self,
+        tenant,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/step-run-queue-metrics",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def tenant_invite_accept(
+        self,
+        accept_invite_request: Optional[AcceptInviteRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Accept tenant invite
+
+        Accepts a tenant invite
+
+        :param accept_invite_request:
+        :type accept_invite_request: AcceptInviteRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_accept_serialize(
+            accept_invite_request=accept_invite_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def tenant_invite_accept_with_http_info(
+        self,
+        accept_invite_request: Optional[AcceptInviteRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Accept tenant invite
+
+        Accepts a tenant invite
+
+        :param accept_invite_request:
+        :type accept_invite_request: AcceptInviteRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_accept_serialize(
+            accept_invite_request=accept_invite_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def tenant_invite_accept_without_preload_content(
+        self,
+        accept_invite_request: Optional[AcceptInviteRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Accept tenant invite
+
+        Accepts a tenant invite
+
+        :param accept_invite_request:
+        :type accept_invite_request: AcceptInviteRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_accept_serialize(
+            accept_invite_request=accept_invite_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _tenant_invite_accept_serialize(
+        self,
+        accept_invite_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if accept_invite_request is not None:
+            _body_params = accept_invite_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/users/invites/accept",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def tenant_invite_create(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        create_tenant_invite_request: Annotated[
+            CreateTenantInviteRequest, Field(description="The tenant invite to create")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> TenantInvite:
+        """Create tenant invite
+
+        Creates a new tenant invite
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param create_tenant_invite_request: The tenant invite to create (required)
+        :type create_tenant_invite_request: CreateTenantInviteRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_create_serialize(
+            tenant=tenant,
+            create_tenant_invite_request=create_tenant_invite_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "201": "TenantInvite",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def tenant_invite_create_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        create_tenant_invite_request: Annotated[
+            CreateTenantInviteRequest, Field(description="The tenant invite to create")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[TenantInvite]:
+        """Create tenant invite
+
+        Creates a new tenant invite
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param create_tenant_invite_request: The tenant invite to create (required)
+        :type create_tenant_invite_request: CreateTenantInviteRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_create_serialize(
+            tenant=tenant,
+            create_tenant_invite_request=create_tenant_invite_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "201": "TenantInvite",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def tenant_invite_create_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        create_tenant_invite_request: Annotated[
+            CreateTenantInviteRequest, Field(description="The tenant invite to create")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Create tenant invite
+
+        Creates a new tenant invite
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param create_tenant_invite_request: The tenant invite to create (required)
+        :type create_tenant_invite_request: CreateTenantInviteRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_create_serialize(
+            tenant=tenant,
+            create_tenant_invite_request=create_tenant_invite_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "201": "TenantInvite",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _tenant_invite_create_serialize(
+        self,
+        tenant,
+        create_tenant_invite_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if create_tenant_invite_request is not None:
+            _body_params = create_tenant_invite_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants/{tenant}/invites",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def tenant_invite_list(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> TenantInviteList:
+        """List tenant invites
+
+        Gets a list of tenant invites
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantInviteList",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def tenant_invite_list_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[TenantInviteList]:
+        """List tenant invites
+
+        Gets a list of tenant invites
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantInviteList",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def tenant_invite_list_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List tenant invites
+
+        Gets a list of tenant invites
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantInviteList",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _tenant_invite_list_serialize(
+        self,
+        tenant,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/invites",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def tenant_invite_reject(
+        self,
+        reject_invite_request: Optional[RejectInviteRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Reject tenant invite
+
+        Rejects a tenant invite
+
+        :param reject_invite_request:
+        :type reject_invite_request: RejectInviteRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_reject_serialize(
+            reject_invite_request=reject_invite_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def tenant_invite_reject_with_http_info(
+        self,
+        reject_invite_request: Optional[RejectInviteRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Reject tenant invite
+
+        Rejects a tenant invite
+
+        :param reject_invite_request:
+        :type reject_invite_request: RejectInviteRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_reject_serialize(
+            reject_invite_request=reject_invite_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def tenant_invite_reject_without_preload_content(
+        self,
+        reject_invite_request: Optional[RejectInviteRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Reject tenant invite
+
+        Rejects a tenant invite
+
+        :param reject_invite_request:
+        :type reject_invite_request: RejectInviteRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_invite_reject_serialize(
+            reject_invite_request=reject_invite_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": None,
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _tenant_invite_reject_serialize(
+        self,
+        reject_invite_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if reject_invite_request is not None:
+            _body_params = reject_invite_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/users/invites/reject",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def tenant_member_delete(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        member: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The tenant member id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> TenantMember:
+        """Delete a tenant member
+
+        Delete a member from a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param member: The tenant member id (required)
+        :type member: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_member_delete_serialize(
+            tenant=tenant,
+            member=member,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": "TenantMember",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def tenant_member_delete_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        member: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The tenant member id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[TenantMember]:
+        """Delete a tenant member
+
+        Delete a member from a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param member: The tenant member id (required)
+        :type member: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_member_delete_serialize(
+            tenant=tenant,
+            member=member,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": "TenantMember",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def tenant_member_delete_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        member: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The tenant member id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Delete a tenant member
+
+        Delete a member from a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param member: The tenant member id (required)
+        :type member: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_member_delete_serialize(
+            tenant=tenant,
+            member=member,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": "TenantMember",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _tenant_member_delete_serialize(
+        self,
+        tenant,
+        member,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if member is not None:
+            _path_params["member"] = member
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="DELETE",
+            resource_path="/api/v1/tenants/{tenant}/members/{member}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def tenant_member_list(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> TenantMemberList:
+        """List tenant members
+
+        Gets a list of tenant members
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_member_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantMemberList",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def tenant_member_list_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[TenantMemberList]:
+        """List tenant members
+
+        Gets a list of tenant members
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_member_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantMemberList",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def tenant_member_list_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List tenant members
+
+        Gets a list of tenant members
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_member_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantMemberList",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _tenant_member_list_serialize(
+        self,
+        tenant,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/members",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def tenant_resource_policy_get(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> TenantResourcePolicy:
+        """Create tenant alert email group
+
+        Gets the resource policy for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_resource_policy_get_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantResourcePolicy",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def tenant_resource_policy_get_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[TenantResourcePolicy]:
+        """Create tenant alert email group
+
+        Gets the resource policy for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_resource_policy_get_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantResourcePolicy",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def tenant_resource_policy_get_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Create tenant alert email group
+
+        Gets the resource policy for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_resource_policy_get_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantResourcePolicy",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _tenant_resource_policy_get_serialize(
+        self,
+        tenant,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/resource-policy",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def tenant_update(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        update_tenant_request: Annotated[
+            UpdateTenantRequest, Field(description="The tenant properties to update")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> Tenant:
+        """Update tenant
+
+        Update an existing tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param update_tenant_request: The tenant properties to update (required)
+        :type update_tenant_request: UpdateTenantRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_update_serialize(
+            tenant=tenant,
+            update_tenant_request=update_tenant_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Tenant",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def tenant_update_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        update_tenant_request: Annotated[
+            UpdateTenantRequest, Field(description="The tenant properties to update")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[Tenant]:
+        """Update tenant
+
+        Update an existing tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param update_tenant_request: The tenant properties to update (required)
+        :type update_tenant_request: UpdateTenantRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_update_serialize(
+            tenant=tenant,
+            update_tenant_request=update_tenant_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Tenant",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def tenant_update_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        update_tenant_request: Annotated[
+            UpdateTenantRequest, Field(description="The tenant properties to update")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Update tenant
+
+        Update an existing tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param update_tenant_request: The tenant properties to update (required)
+        :type update_tenant_request: UpdateTenantRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_update_serialize(
+            tenant=tenant,
+            update_tenant_request=update_tenant_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Tenant",
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _tenant_update_serialize(
+        self,
+        tenant,
+        update_tenant_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if update_tenant_request is not None:
+            _body_params = update_tenant_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="PATCH",
+            resource_path="/api/v1/tenants/{tenant}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def user_list_tenant_invites(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> TenantInviteList:
+        """List tenant invites
+
+        Lists all tenant invites for the current user
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_list_tenant_invites_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantInviteList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def user_list_tenant_invites_with_http_info(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[TenantInviteList]:
+        """List tenant invites
+
+        Lists all tenant invites for the current user
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_list_tenant_invites_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantInviteList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def user_list_tenant_invites_without_preload_content(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List tenant invites
+
+        Lists all tenant invites for the current user
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_list_tenant_invites_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantInviteList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _user_list_tenant_invites_serialize(
+        self,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/users/invites",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/user_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/user_api.py
new file mode 100644
index 00000000..a9e7a35f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/user_api.py
@@ -0,0 +1,2888 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.models.user import User
+from hatchet_sdk.clients.rest.models.user_change_password_request import (
+    UserChangePasswordRequest,
+)
+from hatchet_sdk.clients.rest.models.user_login_request import UserLoginRequest
+from hatchet_sdk.clients.rest.models.user_register_request import UserRegisterRequest
+from hatchet_sdk.clients.rest.models.user_tenant_memberships_list import (
+    UserTenantMembershipsList,
+)
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class UserApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def tenant_memberships_list(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> UserTenantMembershipsList:
+        """List tenant memberships
+
+        Lists all tenant memberships for the current user
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_memberships_list_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "UserTenantMembershipsList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def tenant_memberships_list_with_http_info(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[UserTenantMembershipsList]:
+        """List tenant memberships
+
+        Lists all tenant memberships for the current user
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_memberships_list_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "UserTenantMembershipsList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def tenant_memberships_list_without_preload_content(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """List tenant memberships
+
+        Lists all tenant memberships for the current user
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_memberships_list_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "UserTenantMembershipsList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _tenant_memberships_list_serialize(
+        self,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/users/memberships",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def user_create(
+        self,
+        user_register_request: Optional[UserRegisterRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> User:
+        """Register user
+
+        Registers a user.
+
+        :param user_register_request:
+        :type user_register_request: UserRegisterRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_create_serialize(
+            user_register_request=user_register_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "User",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def user_create_with_http_info(
+        self,
+        user_register_request: Optional[UserRegisterRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[User]:
+        """Register user
+
+        Registers a user.
+
+        :param user_register_request:
+        :type user_register_request: UserRegisterRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_create_serialize(
+            user_register_request=user_register_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "User",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def user_create_without_preload_content(
+        self,
+        user_register_request: Optional[UserRegisterRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Register user
+
+        Registers a user.
+
+        :param user_register_request:
+        :type user_register_request: UserRegisterRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_create_serialize(
+            user_register_request=user_register_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "User",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _user_create_serialize(
+        self,
+        user_register_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if user_register_request is not None:
+            _body_params = user_register_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = []
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/users/register",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def user_get_current(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> User:
+        """Get current user
+
+        Gets the current user
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_get_current_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "User",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def user_get_current_with_http_info(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[User]:
+        """Get current user
+
+        Gets the current user
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_get_current_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "User",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def user_get_current_without_preload_content(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get current user
+
+        Gets the current user
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_get_current_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "User",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _user_get_current_serialize(
+        self,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/users/current",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def user_update_github_oauth_callback(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Complete OAuth flow
+
+        Completes the OAuth flow
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_github_oauth_callback_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def user_update_github_oauth_callback_with_http_info(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Complete OAuth flow
+
+        Completes the OAuth flow
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_github_oauth_callback_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def user_update_github_oauth_callback_without_preload_content(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Complete OAuth flow
+
+        Completes the OAuth flow
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_github_oauth_callback_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _user_update_github_oauth_callback_serialize(
+        self,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # authentication setting
+        _auth_settings: List[str] = []
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/users/github/callback",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def user_update_github_oauth_start(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Start OAuth flow
+
+        Starts the OAuth flow
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_github_oauth_start_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def user_update_github_oauth_start_with_http_info(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Start OAuth flow
+
+        Starts the OAuth flow
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_github_oauth_start_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def user_update_github_oauth_start_without_preload_content(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Start OAuth flow
+
+        Starts the OAuth flow
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_github_oauth_start_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _user_update_github_oauth_start_serialize(
+        self,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # authentication setting
+        _auth_settings: List[str] = []
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/users/github/start",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def user_update_google_oauth_callback(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Complete OAuth flow
+
+        Completes the OAuth flow
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_google_oauth_callback_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def user_update_google_oauth_callback_with_http_info(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Complete OAuth flow
+
+        Completes the OAuth flow
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_google_oauth_callback_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def user_update_google_oauth_callback_without_preload_content(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Complete OAuth flow
+
+        Completes the OAuth flow
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_google_oauth_callback_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _user_update_google_oauth_callback_serialize(
+        self,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # authentication setting
+        _auth_settings: List[str] = []
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/users/google/callback",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def user_update_google_oauth_start(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Start OAuth flow
+
+        Starts the OAuth flow
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_google_oauth_start_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def user_update_google_oauth_start_with_http_info(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Start OAuth flow
+
+        Starts the OAuth flow
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_google_oauth_start_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def user_update_google_oauth_start_without_preload_content(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Start OAuth flow
+
+        Starts the OAuth flow
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_google_oauth_start_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _user_update_google_oauth_start_serialize(
+        self,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # authentication setting
+        _auth_settings: List[str] = []
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/users/google/start",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def user_update_login(
+        self,
+        user_login_request: Optional[UserLoginRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> User:
+        """Login user
+
+        Logs in a user.
+
+        :param user_login_request:
+        :type user_login_request: UserLoginRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_login_serialize(
+            user_login_request=user_login_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "User",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def user_update_login_with_http_info(
+        self,
+        user_login_request: Optional[UserLoginRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[User]:
+        """Login user
+
+        Logs in a user.
+
+        :param user_login_request:
+        :type user_login_request: UserLoginRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_login_serialize(
+            user_login_request=user_login_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "User",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def user_update_login_without_preload_content(
+        self,
+        user_login_request: Optional[UserLoginRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Login user
+
+        Logs in a user.
+
+        :param user_login_request:
+        :type user_login_request: UserLoginRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_login_serialize(
+            user_login_request=user_login_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "User",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _user_update_login_serialize(
+        self,
+        user_login_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if user_login_request is not None:
+            _body_params = user_login_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = []
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/users/login",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def user_update_logout(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> User:
+        """Logout user
+
+        Logs out a user.
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_logout_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "User",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def user_update_logout_with_http_info(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[User]:
+        """Logout user
+
+        Logs out a user.
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_logout_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "User",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def user_update_logout_without_preload_content(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Logout user
+
+        Logs out a user.
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_logout_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "User",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _user_update_logout_serialize(
+        self,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/users/logout",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def user_update_password(
+        self,
+        user_change_password_request: Optional[UserChangePasswordRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> User:
+        """Change user password
+
+        Update a user password.
+
+        :param user_change_password_request:
+        :type user_change_password_request: UserChangePasswordRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_password_serialize(
+            user_change_password_request=user_change_password_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "User",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def user_update_password_with_http_info(
+        self,
+        user_change_password_request: Optional[UserChangePasswordRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[User]:
+        """Change user password
+
+        Update a user password.
+
+        :param user_change_password_request:
+        :type user_change_password_request: UserChangePasswordRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_password_serialize(
+            user_change_password_request=user_change_password_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "User",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def user_update_password_without_preload_content(
+        self,
+        user_change_password_request: Optional[UserChangePasswordRequest] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Change user password
+
+        Update a user password.
+
+        :param user_change_password_request:
+        :type user_change_password_request: UserChangePasswordRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_password_serialize(
+            user_change_password_request=user_change_password_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "User",
+            "400": "APIErrors",
+            "401": "APIErrors",
+            "405": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _user_update_password_serialize(
+        self,
+        user_change_password_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if user_change_password_request is not None:
+            _body_params = user_change_password_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/users/password",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def user_update_slack_oauth_callback(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Complete OAuth flow
+
+        Completes the OAuth flow
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_slack_oauth_callback_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def user_update_slack_oauth_callback_with_http_info(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Complete OAuth flow
+
+        Completes the OAuth flow
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_slack_oauth_callback_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def user_update_slack_oauth_callback_without_preload_content(
+        self,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Complete OAuth flow
+
+        Completes the OAuth flow
+
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_slack_oauth_callback_serialize(
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _user_update_slack_oauth_callback_serialize(
+        self,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/users/slack/callback",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def user_update_slack_oauth_start(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Start OAuth flow
+
+        Starts the OAuth flow
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_slack_oauth_start_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def user_update_slack_oauth_start_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Start OAuth flow
+
+        Starts the OAuth flow
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_slack_oauth_start_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def user_update_slack_oauth_start_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Start OAuth flow
+
+        Starts the OAuth flow
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._user_update_slack_oauth_start_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "302": None,
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _user_update_slack_oauth_start_serialize(
+        self,
+        tenant,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/slack/start",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/worker_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/worker_api.py
new file mode 100644
index 00000000..f1be3e82
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/worker_api.py
@@ -0,0 +1,858 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.models.update_worker_request import UpdateWorkerRequest
+from hatchet_sdk.clients.rest.models.worker import Worker
+from hatchet_sdk.clients.rest.models.worker_list import WorkerList
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class WorkerApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def worker_get(
+        self,
+        worker: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The worker id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> Worker:
+        """Get worker
+
+        Get a worker
+
+        :param worker: The worker id (required)
+        :type worker: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._worker_get_serialize(
+            worker=worker,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Worker",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def worker_get_with_http_info(
+        self,
+        worker: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The worker id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[Worker]:
+        """Get worker
+
+        Get a worker
+
+        :param worker: The worker id (required)
+        :type worker: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._worker_get_serialize(
+            worker=worker,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Worker",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def worker_get_without_preload_content(
+        self,
+        worker: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The worker id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get worker
+
+        Get a worker
+
+        :param worker: The worker id (required)
+        :type worker: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._worker_get_serialize(
+            worker=worker,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Worker",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _worker_get_serialize(
+        self,
+        worker,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if worker is not None:
+            _path_params["worker"] = worker
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/workers/{worker}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def worker_list(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> WorkerList:
+        """Get workers
+
+        Get all workers for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._worker_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkerList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def worker_list_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[WorkerList]:
+        """Get workers
+
+        Get all workers for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._worker_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkerList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def worker_list_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get workers
+
+        Get all workers for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._worker_list_serialize(
+            tenant=tenant,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkerList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _worker_list_serialize(
+        self,
+        tenant,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/worker",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def worker_update(
+        self,
+        worker: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The worker id"
+            ),
+        ],
+        update_worker_request: Annotated[
+            UpdateWorkerRequest, Field(description="The worker update")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> Worker:
+        """Update worker
+
+        Update a worker
+
+        :param worker: The worker id (required)
+        :type worker: str
+        :param update_worker_request: The worker update (required)
+        :type update_worker_request: UpdateWorkerRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._worker_update_serialize(
+            worker=worker,
+            update_worker_request=update_worker_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Worker",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def worker_update_with_http_info(
+        self,
+        worker: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The worker id"
+            ),
+        ],
+        update_worker_request: Annotated[
+            UpdateWorkerRequest, Field(description="The worker update")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[Worker]:
+        """Update worker
+
+        Update a worker
+
+        :param worker: The worker id (required)
+        :type worker: str
+        :param update_worker_request: The worker update (required)
+        :type update_worker_request: UpdateWorkerRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._worker_update_serialize(
+            worker=worker,
+            update_worker_request=update_worker_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Worker",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def worker_update_without_preload_content(
+        self,
+        worker: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The worker id"
+            ),
+        ],
+        update_worker_request: Annotated[
+            UpdateWorkerRequest, Field(description="The worker update")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Update worker
+
+        Update a worker
+
+        :param worker: The worker id (required)
+        :type worker: str
+        :param update_worker_request: The worker update (required)
+        :type update_worker_request: UpdateWorkerRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._worker_update_serialize(
+            worker=worker,
+            update_worker_request=update_worker_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Worker",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _worker_update_serialize(
+        self,
+        worker,
+        update_worker_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if worker is not None:
+            _path_params["worker"] = worker
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if update_worker_request is not None:
+            _body_params = update_worker_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="PATCH",
+            resource_path="/api/v1/workers/{worker}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/workflow_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/workflow_api.py
new file mode 100644
index 00000000..ce4094aa
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/workflow_api.py
@@ -0,0 +1,6310 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from datetime import datetime
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.models.cron_workflows import CronWorkflows
+from hatchet_sdk.clients.rest.models.cron_workflows_list import CronWorkflowsList
+from hatchet_sdk.clients.rest.models.cron_workflows_order_by_field import (
+    CronWorkflowsOrderByField,
+)
+from hatchet_sdk.clients.rest.models.scheduled_run_status import ScheduledRunStatus
+from hatchet_sdk.clients.rest.models.scheduled_workflows import ScheduledWorkflows
+from hatchet_sdk.clients.rest.models.scheduled_workflows_list import (
+    ScheduledWorkflowsList,
+)
+from hatchet_sdk.clients.rest.models.scheduled_workflows_order_by_field import (
+    ScheduledWorkflowsOrderByField,
+)
+from hatchet_sdk.clients.rest.models.tenant_queue_metrics import TenantQueueMetrics
+from hatchet_sdk.clients.rest.models.workflow import Workflow
+from hatchet_sdk.clients.rest.models.workflow_kind import WorkflowKind
+from hatchet_sdk.clients.rest.models.workflow_list import WorkflowList
+from hatchet_sdk.clients.rest.models.workflow_metrics import WorkflowMetrics
+from hatchet_sdk.clients.rest.models.workflow_run import WorkflowRun
+from hatchet_sdk.clients.rest.models.workflow_run_list import WorkflowRunList
+from hatchet_sdk.clients.rest.models.workflow_run_order_by_direction import (
+    WorkflowRunOrderByDirection,
+)
+from hatchet_sdk.clients.rest.models.workflow_run_order_by_field import (
+    WorkflowRunOrderByField,
+)
+from hatchet_sdk.clients.rest.models.workflow_run_shape import WorkflowRunShape
+from hatchet_sdk.clients.rest.models.workflow_run_status import WorkflowRunStatus
+from hatchet_sdk.clients.rest.models.workflow_runs_metrics import WorkflowRunsMetrics
+from hatchet_sdk.clients.rest.models.workflow_update_request import (
+    WorkflowUpdateRequest,
+)
+from hatchet_sdk.clients.rest.models.workflow_version import WorkflowVersion
+from hatchet_sdk.clients.rest.models.workflow_workers_count import WorkflowWorkersCount
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class WorkflowApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def cron_workflow_list(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        workflow_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The workflow id to get runs for."),
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        order_by_field: Annotated[
+            Optional[CronWorkflowsOrderByField], Field(description="The order by field")
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[WorkflowRunOrderByDirection],
+            Field(description="The order by direction"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> CronWorkflowsList:
+        """Get cron job workflows
+
+        Get all cron job workflow triggers for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param workflow_id: The workflow id to get runs for.
+        :type workflow_id: str
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :param order_by_field: The order by field
+        :type order_by_field: CronWorkflowsOrderByField
+        :param order_by_direction: The order by direction
+        :type order_by_direction: WorkflowRunOrderByDirection
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._cron_workflow_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            workflow_id=workflow_id,
+            additional_metadata=additional_metadata,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "CronWorkflowsList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def cron_workflow_list_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        workflow_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The workflow id to get runs for."),
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        order_by_field: Annotated[
+            Optional[CronWorkflowsOrderByField], Field(description="The order by field")
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[WorkflowRunOrderByDirection],
+            Field(description="The order by direction"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[CronWorkflowsList]:
+        """Get cron job workflows
+
+        Get all cron job workflow triggers for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param workflow_id: The workflow id to get runs for.
+        :type workflow_id: str
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :param order_by_field: The order by field
+        :type order_by_field: CronWorkflowsOrderByField
+        :param order_by_direction: The order by direction
+        :type order_by_direction: WorkflowRunOrderByDirection
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._cron_workflow_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            workflow_id=workflow_id,
+            additional_metadata=additional_metadata,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "CronWorkflowsList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def cron_workflow_list_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        workflow_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The workflow id to get runs for."),
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        order_by_field: Annotated[
+            Optional[CronWorkflowsOrderByField], Field(description="The order by field")
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[WorkflowRunOrderByDirection],
+            Field(description="The order by direction"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get cron job workflows
+
+        Get all cron job workflow triggers for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param workflow_id: The workflow id to get runs for.
+        :type workflow_id: str
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :param order_by_field: The order by field
+        :type order_by_field: CronWorkflowsOrderByField
+        :param order_by_direction: The order by direction
+        :type order_by_direction: WorkflowRunOrderByDirection
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._cron_workflow_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            workflow_id=workflow_id,
+            additional_metadata=additional_metadata,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "CronWorkflowsList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _cron_workflow_list_serialize(
+        self,
+        tenant,
+        offset,
+        limit,
+        workflow_id,
+        additional_metadata,
+        order_by_field,
+        order_by_direction,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {
+            "additionalMetadata": "multi",
+        }
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        if offset is not None:
+
+            _query_params.append(("offset", offset))
+
+        if limit is not None:
+
+            _query_params.append(("limit", limit))
+
+        if workflow_id is not None:
+
+            _query_params.append(("workflowId", workflow_id))
+
+        if additional_metadata is not None:
+
+            _query_params.append(("additionalMetadata", additional_metadata))
+
+        if order_by_field is not None:
+
+            _query_params.append(("orderByField", order_by_field.value))
+
+        if order_by_direction is not None:
+
+            _query_params.append(("orderByDirection", order_by_direction.value))
+
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/workflows/crons",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def tenant_get_queue_metrics(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflows: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of workflow IDs to filter by"),
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> TenantQueueMetrics:
+        """Get workflow metrics
+
+        Get the queue metrics for the tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflows: A list of workflow IDs to filter by
+        :type workflows: List[str]
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_get_queue_metrics_serialize(
+            tenant=tenant,
+            workflows=workflows,
+            additional_metadata=additional_metadata,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantQueueMetrics",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def tenant_get_queue_metrics_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflows: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of workflow IDs to filter by"),
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[TenantQueueMetrics]:
+        """Get workflow metrics
+
+        Get the queue metrics for the tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflows: A list of workflow IDs to filter by
+        :type workflows: List[str]
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_get_queue_metrics_serialize(
+            tenant=tenant,
+            workflows=workflows,
+            additional_metadata=additional_metadata,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantQueueMetrics",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def tenant_get_queue_metrics_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflows: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of workflow IDs to filter by"),
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get workflow metrics
+
+        Get the queue metrics for the tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflows: A list of workflow IDs to filter by
+        :type workflows: List[str]
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._tenant_get_queue_metrics_serialize(
+            tenant=tenant,
+            workflows=workflows,
+            additional_metadata=additional_metadata,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "TenantQueueMetrics",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _tenant_get_queue_metrics_serialize(
+        self,
+        tenant,
+        workflows,
+        additional_metadata,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {
+            "workflows": "multi",
+            "additionalMetadata": "multi",
+        }
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        if workflows is not None:
+
+            _query_params.append(("workflows", workflows))
+
+        if additional_metadata is not None:
+
+            _query_params.append(("additionalMetadata", additional_metadata))
+
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/queue-metrics",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_cron_delete(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        cron_workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The cron job id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Delete cron job workflow run
+
+        Delete a cron job workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param cron_workflow: The cron job id (required)
+        :type cron_workflow: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_cron_delete_serialize(
+            tenant=tenant,
+            cron_workflow=cron_workflow,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_cron_delete_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        cron_workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The cron job id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Delete cron job workflow run
+
+        Delete a cron job workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param cron_workflow: The cron job id (required)
+        :type cron_workflow: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_cron_delete_serialize(
+            tenant=tenant,
+            cron_workflow=cron_workflow,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_cron_delete_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        cron_workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The cron job id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Delete cron job workflow run
+
+        Delete a cron job workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param cron_workflow: The cron job id (required)
+        :type cron_workflow: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_cron_delete_serialize(
+            tenant=tenant,
+            cron_workflow=cron_workflow,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_cron_delete_serialize(
+        self,
+        tenant,
+        cron_workflow,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if cron_workflow is not None:
+            _path_params["cron-workflow"] = cron_workflow
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="DELETE",
+            resource_path="/api/v1/tenants/{tenant}/workflows/crons/{cron-workflow}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_cron_get(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        cron_workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The cron job id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> CronWorkflows:
+        """Get cron job workflow run
+
+        Get a cron job workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param cron_workflow: The cron job id (required)
+        :type cron_workflow: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_cron_get_serialize(
+            tenant=tenant,
+            cron_workflow=cron_workflow,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "CronWorkflows",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_cron_get_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        cron_workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The cron job id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[CronWorkflows]:
+        """Get cron job workflow run
+
+        Get a cron job workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param cron_workflow: The cron job id (required)
+        :type cron_workflow: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_cron_get_serialize(
+            tenant=tenant,
+            cron_workflow=cron_workflow,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "CronWorkflows",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_cron_get_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        cron_workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The cron job id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get cron job workflow run
+
+        Get a cron job workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param cron_workflow: The cron job id (required)
+        :type cron_workflow: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_cron_get_serialize(
+            tenant=tenant,
+            cron_workflow=cron_workflow,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "CronWorkflows",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_cron_get_serialize(
+        self,
+        tenant,
+        cron_workflow,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if cron_workflow is not None:
+            _path_params["cron-workflow"] = cron_workflow
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/workflows/crons/{cron-workflow}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_delete(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Delete workflow
+
+        Delete a workflow for a tenant
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_delete_serialize(
+            workflow=workflow,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_delete_with_http_info(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Delete workflow
+
+        Delete a workflow for a tenant
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_delete_serialize(
+            workflow=workflow,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_delete_without_preload_content(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Delete workflow
+
+        Delete a workflow for a tenant
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_delete_serialize(
+            workflow=workflow,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_delete_serialize(
+        self,
+        workflow,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if workflow is not None:
+            _path_params["workflow"] = workflow
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="DELETE",
+            resource_path="/api/v1/workflows/{workflow}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_get(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> Workflow:
+        """Get workflow
+
+        Get a workflow for a tenant
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_get_serialize(
+            workflow=workflow,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Workflow",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_get_with_http_info(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[Workflow]:
+        """Get workflow
+
+        Get a workflow for a tenant
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_get_serialize(
+            workflow=workflow,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Workflow",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_get_without_preload_content(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get workflow
+
+        Get a workflow for a tenant
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_get_serialize(
+            workflow=workflow,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Workflow",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_get_serialize(
+        self,
+        workflow,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if workflow is not None:
+            _path_params["workflow"] = workflow
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/workflows/{workflow}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_get_metrics(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        status: Annotated[
+            Optional[WorkflowRunStatus],
+            Field(description="A status of workflow run statuses to filter by"),
+        ] = None,
+        group_key: Annotated[
+            Optional[StrictStr], Field(description="A group key to filter metrics by")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> WorkflowMetrics:
+        """Get workflow metrics
+
+        Get the metrics for a workflow version
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :param status: A status of workflow run statuses to filter by
+        :type status: WorkflowRunStatus
+        :param group_key: A group key to filter metrics by
+        :type group_key: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_get_metrics_serialize(
+            workflow=workflow,
+            status=status,
+            group_key=group_key,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowMetrics",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_get_metrics_with_http_info(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        status: Annotated[
+            Optional[WorkflowRunStatus],
+            Field(description="A status of workflow run statuses to filter by"),
+        ] = None,
+        group_key: Annotated[
+            Optional[StrictStr], Field(description="A group key to filter metrics by")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[WorkflowMetrics]:
+        """Get workflow metrics
+
+        Get the metrics for a workflow version
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :param status: A status of workflow run statuses to filter by
+        :type status: WorkflowRunStatus
+        :param group_key: A group key to filter metrics by
+        :type group_key: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_get_metrics_serialize(
+            workflow=workflow,
+            status=status,
+            group_key=group_key,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowMetrics",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_get_metrics_without_preload_content(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        status: Annotated[
+            Optional[WorkflowRunStatus],
+            Field(description="A status of workflow run statuses to filter by"),
+        ] = None,
+        group_key: Annotated[
+            Optional[StrictStr], Field(description="A group key to filter metrics by")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get workflow metrics
+
+        Get the metrics for a workflow version
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :param status: A status of workflow run statuses to filter by
+        :type status: WorkflowRunStatus
+        :param group_key: A group key to filter metrics by
+        :type group_key: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_get_metrics_serialize(
+            workflow=workflow,
+            status=status,
+            group_key=group_key,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowMetrics",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_get_metrics_serialize(
+        self,
+        workflow,
+        status,
+        group_key,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if workflow is not None:
+            _path_params["workflow"] = workflow
+        # process the query parameters
+        if status is not None:
+
+            _query_params.append(("status", status.value))
+
+        if group_key is not None:
+
+            _query_params.append(("groupKey", group_key))
+
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/workflows/{workflow}/metrics",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_get_workers_count(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> WorkflowWorkersCount:
+        """Get workflow worker count
+
+        Get a count of the workers available for workflow
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_get_workers_count_serialize(
+            tenant=tenant,
+            workflow=workflow,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowWorkersCount",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_get_workers_count_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[WorkflowWorkersCount]:
+        """Get workflow worker count
+
+        Get a count of the workers available for workflow
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_get_workers_count_serialize(
+            tenant=tenant,
+            workflow=workflow,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowWorkersCount",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_get_workers_count_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get workflow worker count
+
+        Get a count of the workers available for workflow
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_get_workers_count_serialize(
+            tenant=tenant,
+            workflow=workflow,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowWorkersCount",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_get_workers_count_serialize(
+        self,
+        tenant,
+        workflow,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if workflow is not None:
+            _path_params["workflow"] = workflow
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/workflows/{workflow}/worker-count",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_list(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        name: Annotated[
+            Optional[StrictStr], Field(description="Search by name")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> WorkflowList:
+        """Get workflows
+
+        Get all workflows for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param name: Search by name
+        :type name: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            name=name,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_list_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        name: Annotated[
+            Optional[StrictStr], Field(description="Search by name")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[WorkflowList]:
+        """Get workflows
+
+        Get all workflows for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param name: Search by name
+        :type name: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            name=name,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_list_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        name: Annotated[
+            Optional[StrictStr], Field(description="Search by name")
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get workflows
+
+        Get all workflows for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param name: Search by name
+        :type name: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            name=name,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_list_serialize(
+        self,
+        tenant,
+        offset,
+        limit,
+        name,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        if offset is not None:
+
+            _query_params.append(("offset", offset))
+
+        if limit is not None:
+
+            _query_params.append(("limit", limit))
+
+        if name is not None:
+
+            _query_params.append(("name", name))
+
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/workflows",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_run_get(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The workflow run id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> WorkflowRun:
+        """Get workflow run
+
+        Get a workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow_run: The workflow run id (required)
+        :type workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_get_serialize(
+            tenant=tenant,
+            workflow_run=workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowRun",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_run_get_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The workflow run id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[WorkflowRun]:
+        """Get workflow run
+
+        Get a workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow_run: The workflow run id (required)
+        :type workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_get_serialize(
+            tenant=tenant,
+            workflow_run=workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowRun",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_run_get_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The workflow run id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get workflow run
+
+        Get a workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow_run: The workflow run id (required)
+        :type workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_get_serialize(
+            tenant=tenant,
+            workflow_run=workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowRun",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_run_get_serialize(
+        self,
+        tenant,
+        workflow_run,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if workflow_run is not None:
+            _path_params["workflow-run"] = workflow_run
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/workflow-runs/{workflow-run}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_run_get_metrics(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        event_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The event id to get runs for."),
+        ] = None,
+        workflow_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The workflow id to get runs for."),
+        ] = None,
+        parent_workflow_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent workflow run id"),
+        ] = None,
+        parent_step_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent step run id"),
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        created_after: Annotated[
+            Optional[datetime],
+            Field(description="The time after the workflow run was created"),
+        ] = None,
+        created_before: Annotated[
+            Optional[datetime],
+            Field(description="The time before the workflow run was created"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> WorkflowRunsMetrics:
+        """Get workflow runs metrics
+
+        Get a summary of  workflow run metrics for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param event_id: The event id to get runs for.
+        :type event_id: str
+        :param workflow_id: The workflow id to get runs for.
+        :type workflow_id: str
+        :param parent_workflow_run_id: The parent workflow run id
+        :type parent_workflow_run_id: str
+        :param parent_step_run_id: The parent step run id
+        :type parent_step_run_id: str
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :param created_after: The time after the workflow run was created
+        :type created_after: datetime
+        :param created_before: The time before the workflow run was created
+        :type created_before: datetime
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_get_metrics_serialize(
+            tenant=tenant,
+            event_id=event_id,
+            workflow_id=workflow_id,
+            parent_workflow_run_id=parent_workflow_run_id,
+            parent_step_run_id=parent_step_run_id,
+            additional_metadata=additional_metadata,
+            created_after=created_after,
+            created_before=created_before,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowRunsMetrics",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_run_get_metrics_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        event_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The event id to get runs for."),
+        ] = None,
+        workflow_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The workflow id to get runs for."),
+        ] = None,
+        parent_workflow_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent workflow run id"),
+        ] = None,
+        parent_step_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent step run id"),
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        created_after: Annotated[
+            Optional[datetime],
+            Field(description="The time after the workflow run was created"),
+        ] = None,
+        created_before: Annotated[
+            Optional[datetime],
+            Field(description="The time before the workflow run was created"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[WorkflowRunsMetrics]:
+        """Get workflow runs metrics
+
+        Get a summary of  workflow run metrics for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param event_id: The event id to get runs for.
+        :type event_id: str
+        :param workflow_id: The workflow id to get runs for.
+        :type workflow_id: str
+        :param parent_workflow_run_id: The parent workflow run id
+        :type parent_workflow_run_id: str
+        :param parent_step_run_id: The parent step run id
+        :type parent_step_run_id: str
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :param created_after: The time after the workflow run was created
+        :type created_after: datetime
+        :param created_before: The time before the workflow run was created
+        :type created_before: datetime
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_get_metrics_serialize(
+            tenant=tenant,
+            event_id=event_id,
+            workflow_id=workflow_id,
+            parent_workflow_run_id=parent_workflow_run_id,
+            parent_step_run_id=parent_step_run_id,
+            additional_metadata=additional_metadata,
+            created_after=created_after,
+            created_before=created_before,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowRunsMetrics",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_run_get_metrics_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        event_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The event id to get runs for."),
+        ] = None,
+        workflow_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The workflow id to get runs for."),
+        ] = None,
+        parent_workflow_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent workflow run id"),
+        ] = None,
+        parent_step_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent step run id"),
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        created_after: Annotated[
+            Optional[datetime],
+            Field(description="The time after the workflow run was created"),
+        ] = None,
+        created_before: Annotated[
+            Optional[datetime],
+            Field(description="The time before the workflow run was created"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get workflow runs metrics
+
+        Get a summary of  workflow run metrics for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param event_id: The event id to get runs for.
+        :type event_id: str
+        :param workflow_id: The workflow id to get runs for.
+        :type workflow_id: str
+        :param parent_workflow_run_id: The parent workflow run id
+        :type parent_workflow_run_id: str
+        :param parent_step_run_id: The parent step run id
+        :type parent_step_run_id: str
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :param created_after: The time after the workflow run was created
+        :type created_after: datetime
+        :param created_before: The time before the workflow run was created
+        :type created_before: datetime
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_get_metrics_serialize(
+            tenant=tenant,
+            event_id=event_id,
+            workflow_id=workflow_id,
+            parent_workflow_run_id=parent_workflow_run_id,
+            parent_step_run_id=parent_step_run_id,
+            additional_metadata=additional_metadata,
+            created_after=created_after,
+            created_before=created_before,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowRunsMetrics",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_run_get_metrics_serialize(
+        self,
+        tenant,
+        event_id,
+        workflow_id,
+        parent_workflow_run_id,
+        parent_step_run_id,
+        additional_metadata,
+        created_after,
+        created_before,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {
+            "additionalMetadata": "multi",
+        }
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        if event_id is not None:
+
+            _query_params.append(("eventId", event_id))
+
+        if workflow_id is not None:
+
+            _query_params.append(("workflowId", workflow_id))
+
+        if parent_workflow_run_id is not None:
+
+            _query_params.append(("parentWorkflowRunId", parent_workflow_run_id))
+
+        if parent_step_run_id is not None:
+
+            _query_params.append(("parentStepRunId", parent_step_run_id))
+
+        if additional_metadata is not None:
+
+            _query_params.append(("additionalMetadata", additional_metadata))
+
+        if created_after is not None:
+            if isinstance(created_after, datetime):
+                _query_params.append(
+                    (
+                        "createdAfter",
+                        created_after.strftime(
+                            self.api_client.configuration.datetime_format
+                        ),
+                    )
+                )
+            else:
+                _query_params.append(("createdAfter", created_after))
+
+        if created_before is not None:
+            if isinstance(created_before, datetime):
+                _query_params.append(
+                    (
+                        "createdBefore",
+                        created_before.strftime(
+                            self.api_client.configuration.datetime_format
+                        ),
+                    )
+                )
+            else:
+                _query_params.append(("createdBefore", created_before))
+
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/workflows/runs/metrics",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_run_get_shape(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The workflow run id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> WorkflowRunShape:
+        """Get workflow run
+
+        Get a workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow_run: The workflow run id (required)
+        :type workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_get_shape_serialize(
+            tenant=tenant,
+            workflow_run=workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowRunShape",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_run_get_shape_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The workflow run id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[WorkflowRunShape]:
+        """Get workflow run
+
+        Get a workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow_run: The workflow run id (required)
+        :type workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_get_shape_serialize(
+            tenant=tenant,
+            workflow_run=workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowRunShape",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_run_get_shape_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The workflow run id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get workflow run
+
+        Get a workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow_run: The workflow run id (required)
+        :type workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_get_shape_serialize(
+            tenant=tenant,
+            workflow_run=workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowRunShape",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_run_get_shape_serialize(
+        self,
+        tenant,
+        workflow_run,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if workflow_run is not None:
+            _path_params["workflow-run"] = workflow_run
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/workflow-runs/{workflow-run}/shape",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_run_list(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        event_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The event id to get runs for."),
+        ] = None,
+        workflow_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The workflow id to get runs for."),
+        ] = None,
+        parent_workflow_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent workflow run id"),
+        ] = None,
+        parent_step_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent step run id"),
+        ] = None,
+        statuses: Annotated[
+            Optional[List[WorkflowRunStatus]],
+            Field(description="A list of workflow run statuses to filter by"),
+        ] = None,
+        kinds: Annotated[
+            Optional[List[WorkflowKind]],
+            Field(description="A list of workflow kinds to filter by"),
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        created_after: Annotated[
+            Optional[datetime],
+            Field(description="The time after the workflow run was created"),
+        ] = None,
+        created_before: Annotated[
+            Optional[datetime],
+            Field(description="The time before the workflow run was created"),
+        ] = None,
+        finished_after: Annotated[
+            Optional[datetime],
+            Field(description="The time after the workflow run was finished"),
+        ] = None,
+        finished_before: Annotated[
+            Optional[datetime],
+            Field(description="The time before the workflow run was finished"),
+        ] = None,
+        order_by_field: Annotated[
+            Optional[WorkflowRunOrderByField], Field(description="The order by field")
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[WorkflowRunOrderByDirection],
+            Field(description="The order by direction"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> WorkflowRunList:
+        """Get workflow runs
+
+        Get all workflow runs for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param event_id: The event id to get runs for.
+        :type event_id: str
+        :param workflow_id: The workflow id to get runs for.
+        :type workflow_id: str
+        :param parent_workflow_run_id: The parent workflow run id
+        :type parent_workflow_run_id: str
+        :param parent_step_run_id: The parent step run id
+        :type parent_step_run_id: str
+        :param statuses: A list of workflow run statuses to filter by
+        :type statuses: List[WorkflowRunStatus]
+        :param kinds: A list of workflow kinds to filter by
+        :type kinds: List[WorkflowKind]
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :param created_after: The time after the workflow run was created
+        :type created_after: datetime
+        :param created_before: The time before the workflow run was created
+        :type created_before: datetime
+        :param finished_after: The time after the workflow run was finished
+        :type finished_after: datetime
+        :param finished_before: The time before the workflow run was finished
+        :type finished_before: datetime
+        :param order_by_field: The order by field
+        :type order_by_field: WorkflowRunOrderByField
+        :param order_by_direction: The order by direction
+        :type order_by_direction: WorkflowRunOrderByDirection
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            event_id=event_id,
+            workflow_id=workflow_id,
+            parent_workflow_run_id=parent_workflow_run_id,
+            parent_step_run_id=parent_step_run_id,
+            statuses=statuses,
+            kinds=kinds,
+            additional_metadata=additional_metadata,
+            created_after=created_after,
+            created_before=created_before,
+            finished_after=finished_after,
+            finished_before=finished_before,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowRunList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_run_list_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        event_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The event id to get runs for."),
+        ] = None,
+        workflow_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The workflow id to get runs for."),
+        ] = None,
+        parent_workflow_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent workflow run id"),
+        ] = None,
+        parent_step_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent step run id"),
+        ] = None,
+        statuses: Annotated[
+            Optional[List[WorkflowRunStatus]],
+            Field(description="A list of workflow run statuses to filter by"),
+        ] = None,
+        kinds: Annotated[
+            Optional[List[WorkflowKind]],
+            Field(description="A list of workflow kinds to filter by"),
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        created_after: Annotated[
+            Optional[datetime],
+            Field(description="The time after the workflow run was created"),
+        ] = None,
+        created_before: Annotated[
+            Optional[datetime],
+            Field(description="The time before the workflow run was created"),
+        ] = None,
+        finished_after: Annotated[
+            Optional[datetime],
+            Field(description="The time after the workflow run was finished"),
+        ] = None,
+        finished_before: Annotated[
+            Optional[datetime],
+            Field(description="The time before the workflow run was finished"),
+        ] = None,
+        order_by_field: Annotated[
+            Optional[WorkflowRunOrderByField], Field(description="The order by field")
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[WorkflowRunOrderByDirection],
+            Field(description="The order by direction"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[WorkflowRunList]:
+        """Get workflow runs
+
+        Get all workflow runs for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param event_id: The event id to get runs for.
+        :type event_id: str
+        :param workflow_id: The workflow id to get runs for.
+        :type workflow_id: str
+        :param parent_workflow_run_id: The parent workflow run id
+        :type parent_workflow_run_id: str
+        :param parent_step_run_id: The parent step run id
+        :type parent_step_run_id: str
+        :param statuses: A list of workflow run statuses to filter by
+        :type statuses: List[WorkflowRunStatus]
+        :param kinds: A list of workflow kinds to filter by
+        :type kinds: List[WorkflowKind]
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :param created_after: The time after the workflow run was created
+        :type created_after: datetime
+        :param created_before: The time before the workflow run was created
+        :type created_before: datetime
+        :param finished_after: The time after the workflow run was finished
+        :type finished_after: datetime
+        :param finished_before: The time before the workflow run was finished
+        :type finished_before: datetime
+        :param order_by_field: The order by field
+        :type order_by_field: WorkflowRunOrderByField
+        :param order_by_direction: The order by direction
+        :type order_by_direction: WorkflowRunOrderByDirection
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            event_id=event_id,
+            workflow_id=workflow_id,
+            parent_workflow_run_id=parent_workflow_run_id,
+            parent_step_run_id=parent_step_run_id,
+            statuses=statuses,
+            kinds=kinds,
+            additional_metadata=additional_metadata,
+            created_after=created_after,
+            created_before=created_before,
+            finished_after=finished_after,
+            finished_before=finished_before,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowRunList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_run_list_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        event_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The event id to get runs for."),
+        ] = None,
+        workflow_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The workflow id to get runs for."),
+        ] = None,
+        parent_workflow_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent workflow run id"),
+        ] = None,
+        parent_step_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent step run id"),
+        ] = None,
+        statuses: Annotated[
+            Optional[List[WorkflowRunStatus]],
+            Field(description="A list of workflow run statuses to filter by"),
+        ] = None,
+        kinds: Annotated[
+            Optional[List[WorkflowKind]],
+            Field(description="A list of workflow kinds to filter by"),
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        created_after: Annotated[
+            Optional[datetime],
+            Field(description="The time after the workflow run was created"),
+        ] = None,
+        created_before: Annotated[
+            Optional[datetime],
+            Field(description="The time before the workflow run was created"),
+        ] = None,
+        finished_after: Annotated[
+            Optional[datetime],
+            Field(description="The time after the workflow run was finished"),
+        ] = None,
+        finished_before: Annotated[
+            Optional[datetime],
+            Field(description="The time before the workflow run was finished"),
+        ] = None,
+        order_by_field: Annotated[
+            Optional[WorkflowRunOrderByField], Field(description="The order by field")
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[WorkflowRunOrderByDirection],
+            Field(description="The order by direction"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get workflow runs
+
+        Get all workflow runs for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param event_id: The event id to get runs for.
+        :type event_id: str
+        :param workflow_id: The workflow id to get runs for.
+        :type workflow_id: str
+        :param parent_workflow_run_id: The parent workflow run id
+        :type parent_workflow_run_id: str
+        :param parent_step_run_id: The parent step run id
+        :type parent_step_run_id: str
+        :param statuses: A list of workflow run statuses to filter by
+        :type statuses: List[WorkflowRunStatus]
+        :param kinds: A list of workflow kinds to filter by
+        :type kinds: List[WorkflowKind]
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :param created_after: The time after the workflow run was created
+        :type created_after: datetime
+        :param created_before: The time before the workflow run was created
+        :type created_before: datetime
+        :param finished_after: The time after the workflow run was finished
+        :type finished_after: datetime
+        :param finished_before: The time before the workflow run was finished
+        :type finished_before: datetime
+        :param order_by_field: The order by field
+        :type order_by_field: WorkflowRunOrderByField
+        :param order_by_direction: The order by direction
+        :type order_by_direction: WorkflowRunOrderByDirection
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            event_id=event_id,
+            workflow_id=workflow_id,
+            parent_workflow_run_id=parent_workflow_run_id,
+            parent_step_run_id=parent_step_run_id,
+            statuses=statuses,
+            kinds=kinds,
+            additional_metadata=additional_metadata,
+            created_after=created_after,
+            created_before=created_before,
+            finished_after=finished_after,
+            finished_before=finished_before,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowRunList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_run_list_serialize(
+        self,
+        tenant,
+        offset,
+        limit,
+        event_id,
+        workflow_id,
+        parent_workflow_run_id,
+        parent_step_run_id,
+        statuses,
+        kinds,
+        additional_metadata,
+        created_after,
+        created_before,
+        finished_after,
+        finished_before,
+        order_by_field,
+        order_by_direction,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {
+            "statuses": "multi",
+            "kinds": "multi",
+            "additionalMetadata": "multi",
+        }
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        if offset is not None:
+
+            _query_params.append(("offset", offset))
+
+        if limit is not None:
+
+            _query_params.append(("limit", limit))
+
+        if event_id is not None:
+
+            _query_params.append(("eventId", event_id))
+
+        if workflow_id is not None:
+
+            _query_params.append(("workflowId", workflow_id))
+
+        if parent_workflow_run_id is not None:
+
+            _query_params.append(("parentWorkflowRunId", parent_workflow_run_id))
+
+        if parent_step_run_id is not None:
+
+            _query_params.append(("parentStepRunId", parent_step_run_id))
+
+        if statuses is not None:
+
+            _query_params.append(("statuses", statuses))
+
+        if kinds is not None:
+
+            _query_params.append(("kinds", kinds))
+
+        if additional_metadata is not None:
+
+            _query_params.append(("additionalMetadata", additional_metadata))
+
+        if created_after is not None:
+            if isinstance(created_after, datetime):
+                _query_params.append(
+                    (
+                        "createdAfter",
+                        created_after.strftime(
+                            self.api_client.configuration.datetime_format
+                        ),
+                    )
+                )
+            else:
+                _query_params.append(("createdAfter", created_after))
+
+        if created_before is not None:
+            if isinstance(created_before, datetime):
+                _query_params.append(
+                    (
+                        "createdBefore",
+                        created_before.strftime(
+                            self.api_client.configuration.datetime_format
+                        ),
+                    )
+                )
+            else:
+                _query_params.append(("createdBefore", created_before))
+
+        if finished_after is not None:
+            if isinstance(finished_after, datetime):
+                _query_params.append(
+                    (
+                        "finishedAfter",
+                        finished_after.strftime(
+                            self.api_client.configuration.datetime_format
+                        ),
+                    )
+                )
+            else:
+                _query_params.append(("finishedAfter", finished_after))
+
+        if finished_before is not None:
+            if isinstance(finished_before, datetime):
+                _query_params.append(
+                    (
+                        "finishedBefore",
+                        finished_before.strftime(
+                            self.api_client.configuration.datetime_format
+                        ),
+                    )
+                )
+            else:
+                _query_params.append(("finishedBefore", finished_before))
+
+        if order_by_field is not None:
+
+            _query_params.append(("orderByField", order_by_field.value))
+
+        if order_by_direction is not None:
+
+            _query_params.append(("orderByDirection", order_by_direction.value))
+
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/workflows/runs",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_scheduled_delete(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        scheduled_workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The scheduled workflow id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> None:
+        """Delete scheduled workflow run
+
+        Delete a scheduled workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param scheduled_workflow_run: The scheduled workflow id (required)
+        :type scheduled_workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_scheduled_delete_serialize(
+            tenant=tenant,
+            scheduled_workflow_run=scheduled_workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_scheduled_delete_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        scheduled_workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The scheduled workflow id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[None]:
+        """Delete scheduled workflow run
+
+        Delete a scheduled workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param scheduled_workflow_run: The scheduled workflow id (required)
+        :type scheduled_workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_scheduled_delete_serialize(
+            tenant=tenant,
+            scheduled_workflow_run=scheduled_workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_scheduled_delete_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        scheduled_workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The scheduled workflow id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Delete scheduled workflow run
+
+        Delete a scheduled workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param scheduled_workflow_run: The scheduled workflow id (required)
+        :type scheduled_workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_scheduled_delete_serialize(
+            tenant=tenant,
+            scheduled_workflow_run=scheduled_workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "204": None,
+            "400": "APIErrors",
+            "403": "APIError",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_scheduled_delete_serialize(
+        self,
+        tenant,
+        scheduled_workflow_run,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if scheduled_workflow_run is not None:
+            _path_params["scheduled-workflow-run"] = scheduled_workflow_run
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="DELETE",
+            resource_path="/api/v1/tenants/{tenant}/workflows/scheduled/{scheduled-workflow-run}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_scheduled_get(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        scheduled_workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The scheduled workflow id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ScheduledWorkflows:
+        """Get scheduled workflow run
+
+        Get a scheduled workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param scheduled_workflow_run: The scheduled workflow id (required)
+        :type scheduled_workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_scheduled_get_serialize(
+            tenant=tenant,
+            scheduled_workflow_run=scheduled_workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ScheduledWorkflows",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_scheduled_get_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        scheduled_workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The scheduled workflow id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[ScheduledWorkflows]:
+        """Get scheduled workflow run
+
+        Get a scheduled workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param scheduled_workflow_run: The scheduled workflow id (required)
+        :type scheduled_workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_scheduled_get_serialize(
+            tenant=tenant,
+            scheduled_workflow_run=scheduled_workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ScheduledWorkflows",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_scheduled_get_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        scheduled_workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The scheduled workflow id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get scheduled workflow run
+
+        Get a scheduled workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param scheduled_workflow_run: The scheduled workflow id (required)
+        :type scheduled_workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_scheduled_get_serialize(
+            tenant=tenant,
+            scheduled_workflow_run=scheduled_workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ScheduledWorkflows",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_scheduled_get_serialize(
+        self,
+        tenant,
+        scheduled_workflow_run,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if scheduled_workflow_run is not None:
+            _path_params["scheduled-workflow-run"] = scheduled_workflow_run
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/workflows/scheduled/{scheduled-workflow-run}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_scheduled_list(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        order_by_field: Annotated[
+            Optional[ScheduledWorkflowsOrderByField],
+            Field(description="The order by field"),
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[WorkflowRunOrderByDirection],
+            Field(description="The order by direction"),
+        ] = None,
+        workflow_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The workflow id to get runs for."),
+        ] = None,
+        parent_workflow_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent workflow run id"),
+        ] = None,
+        parent_step_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent step run id"),
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        statuses: Annotated[
+            Optional[List[ScheduledRunStatus]],
+            Field(description="A list of scheduled run statuses to filter by"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ScheduledWorkflowsList:
+        """Get scheduled workflow runs
+
+        Get all scheduled workflow runs for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param order_by_field: The order by field
+        :type order_by_field: ScheduledWorkflowsOrderByField
+        :param order_by_direction: The order by direction
+        :type order_by_direction: WorkflowRunOrderByDirection
+        :param workflow_id: The workflow id to get runs for.
+        :type workflow_id: str
+        :param parent_workflow_run_id: The parent workflow run id
+        :type parent_workflow_run_id: str
+        :param parent_step_run_id: The parent step run id
+        :type parent_step_run_id: str
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :param statuses: A list of scheduled run statuses to filter by
+        :type statuses: List[ScheduledRunStatus]
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_scheduled_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            workflow_id=workflow_id,
+            parent_workflow_run_id=parent_workflow_run_id,
+            parent_step_run_id=parent_step_run_id,
+            additional_metadata=additional_metadata,
+            statuses=statuses,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ScheduledWorkflowsList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_scheduled_list_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        order_by_field: Annotated[
+            Optional[ScheduledWorkflowsOrderByField],
+            Field(description="The order by field"),
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[WorkflowRunOrderByDirection],
+            Field(description="The order by direction"),
+        ] = None,
+        workflow_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The workflow id to get runs for."),
+        ] = None,
+        parent_workflow_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent workflow run id"),
+        ] = None,
+        parent_step_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent step run id"),
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        statuses: Annotated[
+            Optional[List[ScheduledRunStatus]],
+            Field(description="A list of scheduled run statuses to filter by"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[ScheduledWorkflowsList]:
+        """Get scheduled workflow runs
+
+        Get all scheduled workflow runs for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param order_by_field: The order by field
+        :type order_by_field: ScheduledWorkflowsOrderByField
+        :param order_by_direction: The order by direction
+        :type order_by_direction: WorkflowRunOrderByDirection
+        :param workflow_id: The workflow id to get runs for.
+        :type workflow_id: str
+        :param parent_workflow_run_id: The parent workflow run id
+        :type parent_workflow_run_id: str
+        :param parent_step_run_id: The parent step run id
+        :type parent_step_run_id: str
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :param statuses: A list of scheduled run statuses to filter by
+        :type statuses: List[ScheduledRunStatus]
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_scheduled_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            workflow_id=workflow_id,
+            parent_workflow_run_id=parent_workflow_run_id,
+            parent_step_run_id=parent_step_run_id,
+            additional_metadata=additional_metadata,
+            statuses=statuses,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ScheduledWorkflowsList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_scheduled_list_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        offset: Annotated[
+            Optional[StrictInt], Field(description="The number to skip")
+        ] = None,
+        limit: Annotated[
+            Optional[StrictInt], Field(description="The number to limit by")
+        ] = None,
+        order_by_field: Annotated[
+            Optional[ScheduledWorkflowsOrderByField],
+            Field(description="The order by field"),
+        ] = None,
+        order_by_direction: Annotated[
+            Optional[WorkflowRunOrderByDirection],
+            Field(description="The order by direction"),
+        ] = None,
+        workflow_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The workflow id to get runs for."),
+        ] = None,
+        parent_workflow_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent workflow run id"),
+        ] = None,
+        parent_step_run_id: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(description="The parent step run id"),
+        ] = None,
+        additional_metadata: Annotated[
+            Optional[List[StrictStr]],
+            Field(description="A list of metadata key value pairs to filter by"),
+        ] = None,
+        statuses: Annotated[
+            Optional[List[ScheduledRunStatus]],
+            Field(description="A list of scheduled run statuses to filter by"),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get scheduled workflow runs
+
+        Get all scheduled workflow runs for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param offset: The number to skip
+        :type offset: int
+        :param limit: The number to limit by
+        :type limit: int
+        :param order_by_field: The order by field
+        :type order_by_field: ScheduledWorkflowsOrderByField
+        :param order_by_direction: The order by direction
+        :type order_by_direction: WorkflowRunOrderByDirection
+        :param workflow_id: The workflow id to get runs for.
+        :type workflow_id: str
+        :param parent_workflow_run_id: The parent workflow run id
+        :type parent_workflow_run_id: str
+        :param parent_step_run_id: The parent step run id
+        :type parent_step_run_id: str
+        :param additional_metadata: A list of metadata key value pairs to filter by
+        :type additional_metadata: List[str]
+        :param statuses: A list of scheduled run statuses to filter by
+        :type statuses: List[ScheduledRunStatus]
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_scheduled_list_serialize(
+            tenant=tenant,
+            offset=offset,
+            limit=limit,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            workflow_id=workflow_id,
+            parent_workflow_run_id=parent_workflow_run_id,
+            parent_step_run_id=parent_step_run_id,
+            additional_metadata=additional_metadata,
+            statuses=statuses,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ScheduledWorkflowsList",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_scheduled_list_serialize(
+        self,
+        tenant,
+        offset,
+        limit,
+        order_by_field,
+        order_by_direction,
+        workflow_id,
+        parent_workflow_run_id,
+        parent_step_run_id,
+        additional_metadata,
+        statuses,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {
+            "additionalMetadata": "multi",
+            "statuses": "multi",
+        }
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        if offset is not None:
+
+            _query_params.append(("offset", offset))
+
+        if limit is not None:
+
+            _query_params.append(("limit", limit))
+
+        if order_by_field is not None:
+
+            _query_params.append(("orderByField", order_by_field.value))
+
+        if order_by_direction is not None:
+
+            _query_params.append(("orderByDirection", order_by_direction.value))
+
+        if workflow_id is not None:
+
+            _query_params.append(("workflowId", workflow_id))
+
+        if parent_workflow_run_id is not None:
+
+            _query_params.append(("parentWorkflowRunId", parent_workflow_run_id))
+
+        if parent_step_run_id is not None:
+
+            _query_params.append(("parentStepRunId", parent_step_run_id))
+
+        if additional_metadata is not None:
+
+            _query_params.append(("additionalMetadata", additional_metadata))
+
+        if statuses is not None:
+
+            _query_params.append(("statuses", statuses))
+
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/workflows/scheduled",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_update(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        workflow_update_request: Annotated[
+            WorkflowUpdateRequest, Field(description="The input to update the workflow")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> Workflow:
+        """Update workflow
+
+        Update a workflow for a tenant
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :param workflow_update_request: The input to update the workflow (required)
+        :type workflow_update_request: WorkflowUpdateRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_update_serialize(
+            workflow=workflow,
+            workflow_update_request=workflow_update_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Workflow",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_update_with_http_info(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        workflow_update_request: Annotated[
+            WorkflowUpdateRequest, Field(description="The input to update the workflow")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[Workflow]:
+        """Update workflow
+
+        Update a workflow for a tenant
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :param workflow_update_request: The input to update the workflow (required)
+        :type workflow_update_request: WorkflowUpdateRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_update_serialize(
+            workflow=workflow,
+            workflow_update_request=workflow_update_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Workflow",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_update_without_preload_content(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        workflow_update_request: Annotated[
+            WorkflowUpdateRequest, Field(description="The input to update the workflow")
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Update workflow
+
+        Update a workflow for a tenant
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :param workflow_update_request: The input to update the workflow (required)
+        :type workflow_update_request: WorkflowUpdateRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_update_serialize(
+            workflow=workflow,
+            workflow_update_request=workflow_update_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Workflow",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_update_serialize(
+        self,
+        workflow,
+        workflow_update_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if workflow is not None:
+            _path_params["workflow"] = workflow
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if workflow_update_request is not None:
+            _body_params = workflow_update_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="PATCH",
+            resource_path="/api/v1/workflows/{workflow}",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_version_get(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        version: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(
+                description="The workflow version. If not supplied, the latest version is fetched."
+            ),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> WorkflowVersion:
+        """Get workflow version
+
+        Get a workflow version for a tenant
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :param version: The workflow version. If not supplied, the latest version is fetched.
+        :type version: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_version_get_serialize(
+            workflow=workflow,
+            version=version,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowVersion",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_version_get_with_http_info(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        version: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(
+                description="The workflow version. If not supplied, the latest version is fetched."
+            ),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[WorkflowVersion]:
+        """Get workflow version
+
+        Get a workflow version for a tenant
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :param version: The workflow version. If not supplied, the latest version is fetched.
+        :type version: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_version_get_serialize(
+            workflow=workflow,
+            version=version,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowVersion",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_version_get_without_preload_content(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        version: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(
+                description="The workflow version. If not supplied, the latest version is fetched."
+            ),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get workflow version
+
+        Get a workflow version for a tenant
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :param version: The workflow version. If not supplied, the latest version is fetched.
+        :type version: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_version_get_serialize(
+            workflow=workflow,
+            version=version,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowVersion",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_version_get_serialize(
+        self,
+        workflow,
+        version,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if workflow is not None:
+            _path_params["workflow"] = workflow
+        # process the query parameters
+        if version is not None:
+
+            _query_params.append(("version", version))
+
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/workflows/{workflow}/versions",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/workflow_run_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/workflow_run_api.py
new file mode 100644
index 00000000..e7feb9f4
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/workflow_run_api.py
@@ -0,0 +1,1932 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.models.create_cron_workflow_trigger_request import (
+    CreateCronWorkflowTriggerRequest,
+)
+from hatchet_sdk.clients.rest.models.cron_workflows import CronWorkflows
+from hatchet_sdk.clients.rest.models.event_update_cancel200_response import (
+    EventUpdateCancel200Response,
+)
+from hatchet_sdk.clients.rest.models.replay_workflow_runs_request import (
+    ReplayWorkflowRunsRequest,
+)
+from hatchet_sdk.clients.rest.models.replay_workflow_runs_response import (
+    ReplayWorkflowRunsResponse,
+)
+from hatchet_sdk.clients.rest.models.schedule_workflow_run_request import (
+    ScheduleWorkflowRunRequest,
+)
+from hatchet_sdk.clients.rest.models.scheduled_workflows import ScheduledWorkflows
+from hatchet_sdk.clients.rest.models.trigger_workflow_run_request import (
+    TriggerWorkflowRunRequest,
+)
+from hatchet_sdk.clients.rest.models.workflow_run import WorkflowRun
+from hatchet_sdk.clients.rest.models.workflow_runs_cancel_request import (
+    WorkflowRunsCancelRequest,
+)
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class WorkflowRunApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def cron_workflow_trigger_create(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow: Annotated[StrictStr, Field(description="The workflow name")],
+        create_cron_workflow_trigger_request: Annotated[
+            CreateCronWorkflowTriggerRequest,
+            Field(description="The input to the cron job workflow trigger"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> CronWorkflows:
+        """Create cron job workflow trigger
+
+        Create a new cron job workflow trigger for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow: The workflow name (required)
+        :type workflow: str
+        :param create_cron_workflow_trigger_request: The input to the cron job workflow trigger (required)
+        :type create_cron_workflow_trigger_request: CreateCronWorkflowTriggerRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._cron_workflow_trigger_create_serialize(
+            tenant=tenant,
+            workflow=workflow,
+            create_cron_workflow_trigger_request=create_cron_workflow_trigger_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "CronWorkflows",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def cron_workflow_trigger_create_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow: Annotated[StrictStr, Field(description="The workflow name")],
+        create_cron_workflow_trigger_request: Annotated[
+            CreateCronWorkflowTriggerRequest,
+            Field(description="The input to the cron job workflow trigger"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[CronWorkflows]:
+        """Create cron job workflow trigger
+
+        Create a new cron job workflow trigger for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow: The workflow name (required)
+        :type workflow: str
+        :param create_cron_workflow_trigger_request: The input to the cron job workflow trigger (required)
+        :type create_cron_workflow_trigger_request: CreateCronWorkflowTriggerRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._cron_workflow_trigger_create_serialize(
+            tenant=tenant,
+            workflow=workflow,
+            create_cron_workflow_trigger_request=create_cron_workflow_trigger_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "CronWorkflows",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def cron_workflow_trigger_create_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow: Annotated[StrictStr, Field(description="The workflow name")],
+        create_cron_workflow_trigger_request: Annotated[
+            CreateCronWorkflowTriggerRequest,
+            Field(description="The input to the cron job workflow trigger"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Create cron job workflow trigger
+
+        Create a new cron job workflow trigger for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow: The workflow name (required)
+        :type workflow: str
+        :param create_cron_workflow_trigger_request: The input to the cron job workflow trigger (required)
+        :type create_cron_workflow_trigger_request: CreateCronWorkflowTriggerRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._cron_workflow_trigger_create_serialize(
+            tenant=tenant,
+            workflow=workflow,
+            create_cron_workflow_trigger_request=create_cron_workflow_trigger_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "CronWorkflows",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _cron_workflow_trigger_create_serialize(
+        self,
+        tenant,
+        workflow,
+        create_cron_workflow_trigger_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if workflow is not None:
+            _path_params["workflow"] = workflow
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if create_cron_workflow_trigger_request is not None:
+            _body_params = create_cron_workflow_trigger_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants/{tenant}/workflows/{workflow}/crons",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def scheduled_workflow_run_create(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow: Annotated[StrictStr, Field(description="The workflow name")],
+        schedule_workflow_run_request: Annotated[
+            ScheduleWorkflowRunRequest,
+            Field(description="The input to the scheduled workflow run"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ScheduledWorkflows:
+        """Trigger workflow run
+
+        Schedule a new workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow: The workflow name (required)
+        :type workflow: str
+        :param schedule_workflow_run_request: The input to the scheduled workflow run (required)
+        :type schedule_workflow_run_request: ScheduleWorkflowRunRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._scheduled_workflow_run_create_serialize(
+            tenant=tenant,
+            workflow=workflow,
+            schedule_workflow_run_request=schedule_workflow_run_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ScheduledWorkflows",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def scheduled_workflow_run_create_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow: Annotated[StrictStr, Field(description="The workflow name")],
+        schedule_workflow_run_request: Annotated[
+            ScheduleWorkflowRunRequest,
+            Field(description="The input to the scheduled workflow run"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[ScheduledWorkflows]:
+        """Trigger workflow run
+
+        Schedule a new workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow: The workflow name (required)
+        :type workflow: str
+        :param schedule_workflow_run_request: The input to the scheduled workflow run (required)
+        :type schedule_workflow_run_request: ScheduleWorkflowRunRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._scheduled_workflow_run_create_serialize(
+            tenant=tenant,
+            workflow=workflow,
+            schedule_workflow_run_request=schedule_workflow_run_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ScheduledWorkflows",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def scheduled_workflow_run_create_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow: Annotated[StrictStr, Field(description="The workflow name")],
+        schedule_workflow_run_request: Annotated[
+            ScheduleWorkflowRunRequest,
+            Field(description="The input to the scheduled workflow run"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Trigger workflow run
+
+        Schedule a new workflow run for a tenant
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow: The workflow name (required)
+        :type workflow: str
+        :param schedule_workflow_run_request: The input to the scheduled workflow run (required)
+        :type schedule_workflow_run_request: ScheduleWorkflowRunRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._scheduled_workflow_run_create_serialize(
+            tenant=tenant,
+            workflow=workflow,
+            schedule_workflow_run_request=schedule_workflow_run_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ScheduledWorkflows",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _scheduled_workflow_run_create_serialize(
+        self,
+        tenant,
+        workflow,
+        schedule_workflow_run_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if workflow is not None:
+            _path_params["workflow"] = workflow
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if schedule_workflow_run_request is not None:
+            _body_params = schedule_workflow_run_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants/{tenant}/workflows/{workflow}/scheduled",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_run_cancel(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow_runs_cancel_request: Annotated[
+            WorkflowRunsCancelRequest,
+            Field(description="The input to cancel the workflow runs"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> EventUpdateCancel200Response:
+        """Cancel workflow runs
+
+        Cancel a batch of workflow runs
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow_runs_cancel_request: The input to cancel the workflow runs (required)
+        :type workflow_runs_cancel_request: WorkflowRunsCancelRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_cancel_serialize(
+            tenant=tenant,
+            workflow_runs_cancel_request=workflow_runs_cancel_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventUpdateCancel200Response",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_run_cancel_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow_runs_cancel_request: Annotated[
+            WorkflowRunsCancelRequest,
+            Field(description="The input to cancel the workflow runs"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[EventUpdateCancel200Response]:
+        """Cancel workflow runs
+
+        Cancel a batch of workflow runs
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow_runs_cancel_request: The input to cancel the workflow runs (required)
+        :type workflow_runs_cancel_request: WorkflowRunsCancelRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_cancel_serialize(
+            tenant=tenant,
+            workflow_runs_cancel_request=workflow_runs_cancel_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventUpdateCancel200Response",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_run_cancel_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow_runs_cancel_request: Annotated[
+            WorkflowRunsCancelRequest,
+            Field(description="The input to cancel the workflow runs"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Cancel workflow runs
+
+        Cancel a batch of workflow runs
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow_runs_cancel_request: The input to cancel the workflow runs (required)
+        :type workflow_runs_cancel_request: WorkflowRunsCancelRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_cancel_serialize(
+            tenant=tenant,
+            workflow_runs_cancel_request=workflow_runs_cancel_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "EventUpdateCancel200Response",
+            "400": "APIErrors",
+            "403": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_run_cancel_serialize(
+        self,
+        tenant,
+        workflow_runs_cancel_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if workflow_runs_cancel_request is not None:
+            _body_params = workflow_runs_cancel_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants/{tenant}/workflows/cancel",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_run_create(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        trigger_workflow_run_request: Annotated[
+            TriggerWorkflowRunRequest,
+            Field(description="The input to the workflow run"),
+        ],
+        version: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(
+                description="The workflow version. If not supplied, the latest version is fetched."
+            ),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> WorkflowRun:
+        """Trigger workflow run
+
+        Trigger a new workflow run for a tenant
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :param trigger_workflow_run_request: The input to the workflow run (required)
+        :type trigger_workflow_run_request: TriggerWorkflowRunRequest
+        :param version: The workflow version. If not supplied, the latest version is fetched.
+        :type version: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_create_serialize(
+            workflow=workflow,
+            trigger_workflow_run_request=trigger_workflow_run_request,
+            version=version,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowRun",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_run_create_with_http_info(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        trigger_workflow_run_request: Annotated[
+            TriggerWorkflowRunRequest,
+            Field(description="The input to the workflow run"),
+        ],
+        version: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(
+                description="The workflow version. If not supplied, the latest version is fetched."
+            ),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[WorkflowRun]:
+        """Trigger workflow run
+
+        Trigger a new workflow run for a tenant
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :param trigger_workflow_run_request: The input to the workflow run (required)
+        :type trigger_workflow_run_request: TriggerWorkflowRunRequest
+        :param version: The workflow version. If not supplied, the latest version is fetched.
+        :type version: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_create_serialize(
+            workflow=workflow,
+            trigger_workflow_run_request=trigger_workflow_run_request,
+            version=version,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowRun",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_run_create_without_preload_content(
+        self,
+        workflow: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The workflow id"
+            ),
+        ],
+        trigger_workflow_run_request: Annotated[
+            TriggerWorkflowRunRequest,
+            Field(description="The input to the workflow run"),
+        ],
+        version: Annotated[
+            Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]],
+            Field(
+                description="The workflow version. If not supplied, the latest version is fetched."
+            ),
+        ] = None,
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Trigger workflow run
+
+        Trigger a new workflow run for a tenant
+
+        :param workflow: The workflow id (required)
+        :type workflow: str
+        :param trigger_workflow_run_request: The input to the workflow run (required)
+        :type trigger_workflow_run_request: TriggerWorkflowRunRequest
+        :param version: The workflow version. If not supplied, the latest version is fetched.
+        :type version: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_create_serialize(
+            workflow=workflow,
+            trigger_workflow_run_request=trigger_workflow_run_request,
+            version=version,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "WorkflowRun",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_run_create_serialize(
+        self,
+        workflow,
+        trigger_workflow_run_request,
+        version,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if workflow is not None:
+            _path_params["workflow"] = workflow
+        # process the query parameters
+        if version is not None:
+
+            _query_params.append(("version", version))
+
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if trigger_workflow_run_request is not None:
+            _body_params = trigger_workflow_run_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/workflows/{workflow}/trigger",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_run_get_input(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The workflow run id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> Dict[str, object]:
+        """Get workflow run input
+
+        Get the input for a workflow run.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow_run: The workflow run id (required)
+        :type workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_get_input_serialize(
+            tenant=tenant,
+            workflow_run=workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Dict[str, object]",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_run_get_input_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The workflow run id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[Dict[str, object]]:
+        """Get workflow run input
+
+        Get the input for a workflow run.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow_run: The workflow run id (required)
+        :type workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_get_input_serialize(
+            tenant=tenant,
+            workflow_run=workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Dict[str, object]",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_run_get_input_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The workflow run id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get workflow run input
+
+        Get the input for a workflow run.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param workflow_run: The workflow run id (required)
+        :type workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_get_input_serialize(
+            tenant=tenant,
+            workflow_run=workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Dict[str, object]",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_run_get_input_serialize(
+        self,
+        tenant,
+        workflow_run,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        if workflow_run is not None:
+            _path_params["workflow-run"] = workflow_run
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/tenants/{tenant}/workflow-runs/{workflow-run}/input",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_run_update_replay(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        replay_workflow_runs_request: Annotated[
+            ReplayWorkflowRunsRequest,
+            Field(description="The workflow run ids to replay"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ReplayWorkflowRunsResponse:
+        """Replay workflow runs
+
+        Replays a list of workflow runs.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param replay_workflow_runs_request: The workflow run ids to replay (required)
+        :type replay_workflow_runs_request: ReplayWorkflowRunsRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_update_replay_serialize(
+            tenant=tenant,
+            replay_workflow_runs_request=replay_workflow_runs_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ReplayWorkflowRunsResponse",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_run_update_replay_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        replay_workflow_runs_request: Annotated[
+            ReplayWorkflowRunsRequest,
+            Field(description="The workflow run ids to replay"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[ReplayWorkflowRunsResponse]:
+        """Replay workflow runs
+
+        Replays a list of workflow runs.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param replay_workflow_runs_request: The workflow run ids to replay (required)
+        :type replay_workflow_runs_request: ReplayWorkflowRunsRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_update_replay_serialize(
+            tenant=tenant,
+            replay_workflow_runs_request=replay_workflow_runs_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ReplayWorkflowRunsResponse",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_run_update_replay_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        replay_workflow_runs_request: Annotated[
+            ReplayWorkflowRunsRequest,
+            Field(description="The workflow run ids to replay"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Replay workflow runs
+
+        Replays a list of workflow runs.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param replay_workflow_runs_request: The workflow run ids to replay (required)
+        :type replay_workflow_runs_request: ReplayWorkflowRunsRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_update_replay_serialize(
+            tenant=tenant,
+            replay_workflow_runs_request=replay_workflow_runs_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ReplayWorkflowRunsResponse",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_run_update_replay_serialize(
+        self,
+        tenant,
+        replay_workflow_runs_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[
+            str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+        ] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if replay_workflow_runs_request is not None:
+            _body_params = replay_workflow_runs_request
+
+        # set the HTTP header `Accept`
+        if "Accept" not in _header_params:
+            _header_params["Accept"] = self.api_client.select_header_accept(
+                ["application/json"]
+            )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants/{tenant}/workflow-runs/replay",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/workflow_runs_api.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/workflow_runs_api.py
new file mode 100644
index 00000000..0572380b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api/workflow_runs_api.py
@@ -0,0 +1,610 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 warnings
+from typing import Any, Dict, List, Optional, Tuple, Union
+
+from pydantic import Field, StrictFloat, StrictInt, StrictStr, validate_call
+from typing_extensions import Annotated
+
+from hatchet_sdk.clients.rest.api_client import ApiClient, RequestSerialized
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.models.replay_workflow_runs_request import (
+    ReplayWorkflowRunsRequest,
+)
+from hatchet_sdk.clients.rest.models.replay_workflow_runs_response import (
+    ReplayWorkflowRunsResponse,
+)
+from hatchet_sdk.clients.rest.rest import RESTResponseType
+
+
+class WorkflowRunsApi:
+    """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) -> None:
+        if api_client is None:
+            api_client = ApiClient.get_default()
+        self.api_client = api_client
+
+    @validate_call
+    async def workflow_run_get_input(
+        self,
+        workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The workflow run id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> Dict[str, object]:
+        """Get workflow run input
+
+        Get the input for a workflow run.
+
+        :param workflow_run: The workflow run id (required)
+        :type workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_get_input_serialize(
+            workflow_run=workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Dict[str, object]",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_run_get_input_with_http_info(
+        self,
+        workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The workflow run id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[Dict[str, object]]:
+        """Get workflow run input
+
+        Get the input for a workflow run.
+
+        :param workflow_run: The workflow run id (required)
+        :type workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_get_input_serialize(
+            workflow_run=workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Dict[str, object]",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_run_get_input_without_preload_content(
+        self,
+        workflow_run: Annotated[
+            str,
+            Field(
+                min_length=36,
+                strict=True,
+                max_length=36,
+                description="The workflow run id",
+            ),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Get workflow run input
+
+        Get the input for a workflow run.
+
+        :param workflow_run: The workflow run id (required)
+        :type workflow_run: str
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_get_input_serialize(
+            workflow_run=workflow_run,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "Dict[str, object]",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "404": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_run_get_input_serialize(
+        self,
+        workflow_run,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[str, Union[str, bytes]] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if workflow_run is not None:
+            _path_params["workflow-run"] = workflow_run
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+
+        # set the HTTP header `Accept`
+        _header_params["Accept"] = self.api_client.select_header_accept(
+            ["application/json"]
+        )
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="GET",
+            resource_path="/api/v1/workflow-runs/{workflow-run}/input",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
+
+    @validate_call
+    async def workflow_run_update_replay(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        replay_workflow_runs_request: Annotated[
+            ReplayWorkflowRunsRequest,
+            Field(description="The workflow run ids to replay"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ReplayWorkflowRunsResponse:
+        """Replay workflow runs
+
+        Replays a list of workflow runs.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param replay_workflow_runs_request: The workflow run ids to replay (required)
+        :type replay_workflow_runs_request: ReplayWorkflowRunsRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_update_replay_serialize(
+            tenant=tenant,
+            replay_workflow_runs_request=replay_workflow_runs_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ReplayWorkflowRunsResponse",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        ).data
+
+    @validate_call
+    async def workflow_run_update_replay_with_http_info(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        replay_workflow_runs_request: Annotated[
+            ReplayWorkflowRunsRequest,
+            Field(description="The workflow run ids to replay"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> ApiResponse[ReplayWorkflowRunsResponse]:
+        """Replay workflow runs
+
+        Replays a list of workflow runs.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param replay_workflow_runs_request: The workflow run ids to replay (required)
+        :type replay_workflow_runs_request: ReplayWorkflowRunsRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_update_replay_serialize(
+            tenant=tenant,
+            replay_workflow_runs_request=replay_workflow_runs_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ReplayWorkflowRunsResponse",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        await response_data.read()
+        return self.api_client.response_deserialize(
+            response_data=response_data,
+            response_types_map=_response_types_map,
+        )
+
+    @validate_call
+    async def workflow_run_update_replay_without_preload_content(
+        self,
+        tenant: Annotated[
+            str,
+            Field(
+                min_length=36, strict=True, max_length=36, description="The tenant id"
+            ),
+        ],
+        replay_workflow_runs_request: Annotated[
+            ReplayWorkflowRunsRequest,
+            Field(description="The workflow run ids to replay"),
+        ],
+        _request_timeout: Union[
+            None,
+            Annotated[StrictFloat, Field(gt=0)],
+            Tuple[
+                Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
+            ],
+        ] = None,
+        _request_auth: Optional[Dict[StrictStr, Any]] = None,
+        _content_type: Optional[StrictStr] = None,
+        _headers: Optional[Dict[StrictStr, Any]] = None,
+        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+    ) -> RESTResponseType:
+        """Replay workflow runs
+
+        Replays a list of workflow runs.
+
+        :param tenant: The tenant id (required)
+        :type tenant: str
+        :param replay_workflow_runs_request: The workflow run ids to replay (required)
+        :type replay_workflow_runs_request: ReplayWorkflowRunsRequest
+        :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.
+        :type _request_timeout: int, tuple(int, int), optional
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the
+                              authentication in the spec for a single request.
+        :type _request_auth: dict, optional
+        :param _content_type: force content-type for the request.
+        :type _content_type: str, Optional
+        :param _headers: set to override the headers for a single
+                         request; this effectively ignores the headers
+                         in the spec for a single request.
+        :type _headers: dict, optional
+        :param _host_index: set to override the host_index for a single
+                            request; this effectively ignores the host_index
+                            in the spec for a single request.
+        :type _host_index: int, optional
+        :return: Returns the result object.
+        """  # noqa: E501
+
+        _param = self._workflow_run_update_replay_serialize(
+            tenant=tenant,
+            replay_workflow_runs_request=replay_workflow_runs_request,
+            _request_auth=_request_auth,
+            _content_type=_content_type,
+            _headers=_headers,
+            _host_index=_host_index,
+        )
+
+        _response_types_map: Dict[str, Optional[str]] = {
+            "200": "ReplayWorkflowRunsResponse",
+            "400": "APIErrors",
+            "403": "APIErrors",
+            "429": "APIErrors",
+        }
+        response_data = await self.api_client.call_api(
+            *_param, _request_timeout=_request_timeout
+        )
+        return response_data.response
+
+    def _workflow_run_update_replay_serialize(
+        self,
+        tenant,
+        replay_workflow_runs_request,
+        _request_auth,
+        _content_type,
+        _headers,
+        _host_index,
+    ) -> RequestSerialized:
+
+        _host = None
+
+        _collection_formats: Dict[str, str] = {}
+
+        _path_params: Dict[str, str] = {}
+        _query_params: List[Tuple[str, str]] = []
+        _header_params: Dict[str, Optional[str]] = _headers or {}
+        _form_params: List[Tuple[str, str]] = []
+        _files: Dict[str, Union[str, bytes]] = {}
+        _body_params: Optional[bytes] = None
+
+        # process the path parameters
+        if tenant is not None:
+            _path_params["tenant"] = tenant
+        # process the query parameters
+        # process the header parameters
+        # process the form parameters
+        # process the body parameter
+        if replay_workflow_runs_request is not None:
+            _body_params = replay_workflow_runs_request
+
+        # set the HTTP header `Accept`
+        _header_params["Accept"] = self.api_client.select_header_accept(
+            ["application/json"]
+        )
+
+        # set the HTTP header `Content-Type`
+        if _content_type:
+            _header_params["Content-Type"] = _content_type
+        else:
+            _default_content_type = self.api_client.select_header_content_type(
+                ["application/json"]
+            )
+            if _default_content_type is not None:
+                _header_params["Content-Type"] = _default_content_type
+
+        # authentication setting
+        _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
+
+        return self.api_client.param_serialize(
+            method="POST",
+            resource_path="/api/v1/tenants/{tenant}/workflow-runs/replay",
+            path_params=_path_params,
+            query_params=_query_params,
+            header_params=_header_params,
+            body=_body_params,
+            post_params=_form_params,
+            files=_files,
+            auth_settings=_auth_settings,
+            collection_formats=_collection_formats,
+            _host=_host,
+            _request_auth=_request_auth,
+        )
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api_client.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api_client.py
new file mode 100644
index 00000000..76446dda
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api_client.py
@@ -0,0 +1,759 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 datetime
+import decimal
+import json
+import mimetypes
+import os
+import re
+import tempfile
+from enum import Enum
+from typing import Dict, List, Optional, Tuple, Union
+from urllib.parse import quote
+
+from dateutil.parser import parse
+from pydantic import SecretStr
+
+import hatchet_sdk.clients.rest.models
+from hatchet_sdk.clients.rest import rest
+from hatchet_sdk.clients.rest.api_response import ApiResponse
+from hatchet_sdk.clients.rest.api_response import T as ApiResponseT
+from hatchet_sdk.clients.rest.configuration import Configuration
+from hatchet_sdk.clients.rest.exceptions import (
+    ApiException,
+    ApiValueError,
+    BadRequestException,
+    ForbiddenException,
+    NotFoundException,
+    ServiceException,
+    UnauthorizedException,
+)
+
+RequestSerialized = Tuple[str, str, Dict[str, str], Optional[str], List[str]]
+
+
+class ApiClient:
+    """Generic API client for OpenAPI client library builds.
+
+    OpenAPI generic API client. This client handles the client-
+    server communication, and is invariant across implementations. Specifics of
+    the methods and models for each application are generated from the OpenAPI
+    templates.
+
+    :param configuration: .Configuration object for this client
+    :param header_name: a header to pass when making calls to the API.
+    :param header_value: a header value to pass when making calls to
+        the API.
+    :param cookie: a cookie to include in the header when making calls
+        to the API
+    """
+
+    PRIMITIVE_TYPES = (float, bool, bytes, str, int)
+    NATIVE_TYPES_MAPPING = {
+        "int": int,
+        "long": int,  # TODO remove as only py3 is supported?
+        "float": float,
+        "str": str,
+        "bool": bool,
+        "date": datetime.date,
+        "datetime": datetime.datetime,
+        "decimal": decimal.Decimal,
+        "object": object,
+    }
+    _pool = None
+
+    def __init__(
+        self, configuration=None, header_name=None, header_value=None, cookie=None
+    ) -> None:
+        # use default configuration if none is provided
+        if configuration is None:
+            configuration = Configuration.get_default()
+        self.configuration = configuration
+
+        self.rest_client = rest.RESTClientObject(configuration)
+        self.default_headers = {}
+        if header_name is not None:
+            self.default_headers[header_name] = header_value
+        self.cookie = cookie
+        # Set default User-Agent.
+        self.user_agent = "OpenAPI-Generator/1.0.0/python"
+        self.client_side_validation = configuration.client_side_validation
+
+    async def __aenter__(self):
+        return self
+
+    async def __aexit__(self, exc_type, exc_value, traceback):
+        await self.close()
+
+    async def close(self):
+        await self.rest_client.close()
+
+    @property
+    def user_agent(self):
+        """User agent for this API client"""
+        return self.default_headers["User-Agent"]
+
+    @user_agent.setter
+    def user_agent(self, value):
+        self.default_headers["User-Agent"] = value
+
+    def set_default_header(self, header_name, header_value):
+        self.default_headers[header_name] = header_value
+
+    _default = None
+
+    @classmethod
+    def get_default(cls):
+        """Return new instance of ApiClient.
+
+        This method returns newly created, based on default constructor,
+        object of ApiClient class or returns a copy of default
+        ApiClient.
+
+        :return: The ApiClient object.
+        """
+        if cls._default is None:
+            cls._default = ApiClient()
+        return cls._default
+
+    @classmethod
+    def set_default(cls, default):
+        """Set default instance of ApiClient.
+
+        It stores default ApiClient.
+
+        :param default: object of ApiClient.
+        """
+        cls._default = default
+
+    def param_serialize(
+        self,
+        method,
+        resource_path,
+        path_params=None,
+        query_params=None,
+        header_params=None,
+        body=None,
+        post_params=None,
+        files=None,
+        auth_settings=None,
+        collection_formats=None,
+        _host=None,
+        _request_auth=None,
+    ) -> RequestSerialized:
+        """Builds the HTTP request params needed by the request.
+        :param method: Method to call.
+        :param resource_path: Path to method endpoint.
+        :param path_params: Path parameters in the url.
+        :param query_params: Query parameters in the url.
+        :param header_params: Header parameters to be
+            placed in the request header.
+        :param body: Request body.
+        :param post_params dict: Request post form parameters,
+            for `application/x-www-form-urlencoded`, `multipart/form-data`.
+        :param auth_settings list: Auth Settings names for the request.
+        :param files dict: key -> filename, value -> filepath,
+            for `multipart/form-data`.
+        :param collection_formats: dict of collection formats for path, query,
+            header, and post parameters.
+        :param _request_auth: set to override the auth_settings for an a single
+                              request; this effectively ignores the authentication
+                              in the spec for a single request.
+        :return: tuple of form (path, http_method, query_params, header_params,
+            body, post_params, files)
+        """
+
+        config = self.configuration
+
+        # header parameters
+        header_params = header_params or {}
+        header_params.update(self.default_headers)
+        if self.cookie:
+            header_params["Cookie"] = self.cookie
+        if header_params:
+            header_params = self.sanitize_for_serialization(header_params)
+            header_params = dict(
+                self.parameters_to_tuples(header_params, collection_formats)
+            )
+
+        # path parameters
+        if path_params:
+            path_params = self.sanitize_for_serialization(path_params)
+            path_params = self.parameters_to_tuples(path_params, collection_formats)
+            for k, v in path_params:
+                # specified safe chars, encode everything
+                resource_path = resource_path.replace(
+                    "{%s}" % k, quote(str(v), safe=config.safe_chars_for_path_param)
+                )
+
+        # post parameters
+        if post_params or files:
+            post_params = post_params if post_params else []
+            post_params = self.sanitize_for_serialization(post_params)
+            post_params = self.parameters_to_tuples(post_params, collection_formats)
+            if files:
+                post_params.extend(self.files_parameters(files))
+
+        # auth setting
+        self.update_params_for_auth(
+            header_params,
+            query_params,
+            auth_settings,
+            resource_path,
+            method,
+            body,
+            request_auth=_request_auth,
+        )
+
+        # body
+        if body:
+            body = self.sanitize_for_serialization(body)
+
+        # request url
+        if _host is None or self.configuration.ignore_operation_servers:
+            url = self.configuration.host + resource_path
+        else:
+            # use server/host defined in path or operation instead
+            url = _host + resource_path
+
+        # query parameters
+        if query_params:
+            query_params = self.sanitize_for_serialization(query_params)
+            url_query = self.parameters_to_url_query(query_params, collection_formats)
+            url += "?" + url_query
+
+        return method, url, header_params, body, post_params
+
+    async def call_api(
+        self,
+        method,
+        url,
+        header_params=None,
+        body=None,
+        post_params=None,
+        _request_timeout=None,
+    ) -> rest.RESTResponse:
+        """Makes the HTTP request (synchronous)
+        :param method: Method to call.
+        :param url: Path to method endpoint.
+        :param header_params: Header parameters to be
+            placed in the request header.
+        :param body: Request body.
+        :param post_params dict: Request post form parameters,
+            for `application/x-www-form-urlencoded`, `multipart/form-data`.
+        :param _request_timeout: timeout setting for this request.
+        :return: RESTResponse
+        """
+
+        try:
+            # perform request and return response
+            response_data = await self.rest_client.request(
+                method,
+                url,
+                headers=header_params,
+                body=body,
+                post_params=post_params,
+                _request_timeout=_request_timeout,
+            )
+
+        except ApiException as e:
+            raise e
+
+        return response_data
+
+    def response_deserialize(
+        self,
+        response_data: rest.RESTResponse,
+        response_types_map: Optional[Dict[str, ApiResponseT]] = None,
+    ) -> ApiResponse[ApiResponseT]:
+        """Deserializes response into an object.
+        :param response_data: RESTResponse object to be deserialized.
+        :param response_types_map: dict of response types.
+        :return: ApiResponse
+        """
+
+        msg = "RESTResponse.read() must be called before passing it to response_deserialize()"
+        assert response_data.data is not None, msg
+
+        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
+            )
+
+        # deserialize response data
+        response_text = None
+        return_data = None
+        try:
+            if response_type == "bytearray":
+                return_data = response_data.data
+            elif response_type == "file":
+                return_data = self.__deserialize_file(response_data)
+            elif response_type is not None:
+                match = None
+                content_type = response_data.getheader("content-type")
+                if content_type is not None:
+                    match = re.search(r"charset=([a-zA-Z\-\d]+)[\s;]?", content_type)
+                encoding = match.group(1) if match else "utf-8"
+                response_text = response_data.data.decode(encoding)
+                return_data = self.deserialize(
+                    response_text, response_type, content_type
+                )
+        finally:
+            if not 200 <= response_data.status <= 299:
+                raise ApiException.from_response(
+                    http_resp=response_data,
+                    body=response_text,
+                    data=return_data,
+                )
+
+        return ApiResponse(
+            status_code=response_data.status,
+            data=return_data,
+            headers=response_data.getheaders(),
+            raw_data=response_data.data,
+        )
+
+    def sanitize_for_serialization(self, obj):
+        """Builds a JSON POST object.
+
+        If obj is None, return None.
+        If obj is SecretStr, return obj.get_secret_value()
+        If obj is str, int, long, float, bool, return directly.
+        If obj is datetime.datetime, datetime.date
+            convert to string in iso8601 format.
+        If obj is decimal.Decimal return string representation.
+        If obj is list, sanitize each element in the list.
+        If obj is dict, return the dict.
+        If obj is OpenAPI model, return the properties dict.
+
+        :param obj: The data to serialize.
+        :return: The serialized form of data.
+        """
+        if obj is None:
+            return None
+        elif isinstance(obj, Enum):
+            return obj.value
+        elif isinstance(obj, SecretStr):
+            return obj.get_secret_value()
+        elif isinstance(obj, self.PRIMITIVE_TYPES):
+            return obj
+        elif isinstance(obj, list):
+            return [self.sanitize_for_serialization(sub_obj) for sub_obj in obj]
+        elif isinstance(obj, tuple):
+            return tuple(self.sanitize_for_serialization(sub_obj) for sub_obj in obj)
+        elif isinstance(obj, (datetime.datetime, datetime.date)):
+            return obj.isoformat()
+        elif isinstance(obj, decimal.Decimal):
+            return str(obj)
+
+        elif isinstance(obj, dict):
+            obj_dict = obj
+        else:
+            # Convert model obj to dict except
+            # attributes `openapi_types`, `attribute_map`
+            # and attributes which value is not None.
+            # Convert attribute name to json key in
+            # model definition for request.
+            if hasattr(obj, "to_dict") and callable(getattr(obj, "to_dict")):
+                obj_dict = obj.to_dict()
+            else:
+                obj_dict = obj.__dict__
+
+        return {
+            key: self.sanitize_for_serialization(val) for key, val in obj_dict.items()
+        }
+
+    def deserialize(
+        self, response_text: str, response_type: str, content_type: Optional[str]
+    ):
+        """Deserializes response into an object.
+
+        :param response: RESTResponse object to be deserialized.
+        :param response_type: class literal for
+            deserialized object, or string of class name.
+        :param content_type: content type of response.
+
+        :return: deserialized object.
+        """
+
+        # fetch data from response object
+        if content_type is None:
+            try:
+                data = json.loads(response_text)
+            except ValueError:
+                data = response_text
+        elif re.match(
+            r"^application/(json|[\w!#$&.+-^_]+\+json)\s*(;|$)",
+            content_type,
+            re.IGNORECASE,
+        ):
+            if response_text == "":
+                data = ""
+            else:
+                data = json.loads(response_text)
+        elif re.match(r"^text\/[a-z.+-]+\s*(;|$)", content_type, re.IGNORECASE):
+            data = response_text
+        else:
+            raise ApiException(
+                status=0, reason="Unsupported content type: {0}".format(content_type)
+            )
+
+        return self.__deserialize(data, response_type)
+
+    def __deserialize(self, data, klass):
+        """Deserializes dict, list, str into an object.
+
+        :param data: dict, list or str.
+        :param klass: class literal, or string of class name.
+
+        :return: object.
+        """
+        if data is None:
+            return None
+
+        if isinstance(klass, str):
+            if klass.startswith("List["):
+                m = re.match(r"List\[(.*)]", klass)
+                assert m is not None, "Malformed List type definition"
+                sub_kls = m.group(1)
+                return [self.__deserialize(sub_data, sub_kls) for sub_data in data]
+
+            if klass.startswith("Dict["):
+                m = re.match(r"Dict\[([^,]*), (.*)]", klass)
+                assert m is not None, "Malformed Dict type definition"
+                sub_kls = m.group(2)
+                return {k: self.__deserialize(v, sub_kls) for k, v in data.items()}
+
+            # convert str to class
+            if klass in self.NATIVE_TYPES_MAPPING:
+                klass = self.NATIVE_TYPES_MAPPING[klass]
+            else:
+                klass = getattr(hatchet_sdk.clients.rest.models, klass)
+
+        if klass in self.PRIMITIVE_TYPES:
+            return self.__deserialize_primitive(data, klass)
+        elif klass == object:
+            return self.__deserialize_object(data)
+        elif klass == datetime.date:
+            return self.__deserialize_date(data)
+        elif klass == datetime.datetime:
+            return self.__deserialize_datetime(data)
+        elif klass == decimal.Decimal:
+            return decimal.Decimal(data)
+        elif issubclass(klass, Enum):
+            return self.__deserialize_enum(data, klass)
+        else:
+            return self.__deserialize_model(data, klass)
+
+    def parameters_to_tuples(self, params, collection_formats):
+        """Get parameters as list of tuples, formatting collections.
+
+        :param params: Parameters as dict or list of two-tuples
+        :param dict collection_formats: Parameter collection formats
+        :return: Parameters as list of tuples, collections formatted
+        """
+        new_params: List[Tuple[str, str]] = []
+        if collection_formats is None:
+            collection_formats = {}
+        for k, v in params.items() if isinstance(params, dict) else params:
+            if k in collection_formats:
+                collection_format = collection_formats[k]
+                if collection_format == "multi":
+                    new_params.extend((k, value) for value in v)
+                else:
+                    if collection_format == "ssv":
+                        delimiter = " "
+                    elif collection_format == "tsv":
+                        delimiter = "\t"
+                    elif collection_format == "pipes":
+                        delimiter = "|"
+                    else:  # csv is the default
+                        delimiter = ","
+                    new_params.append((k, delimiter.join(str(value) for value in v)))
+            else:
+                new_params.append((k, v))
+        return new_params
+
+    def parameters_to_url_query(self, params, collection_formats):
+        """Get parameters as list of tuples, formatting collections.
+
+        :param params: Parameters as dict or list of two-tuples
+        :param dict collection_formats: Parameter collection formats
+        :return: URL query string (e.g. a=Hello%20World&b=123)
+        """
+        new_params: List[Tuple[str, str]] = []
+        if collection_formats is None:
+            collection_formats = {}
+        for k, v in params.items() if isinstance(params, dict) else params:
+            if isinstance(v, bool):
+                v = str(v).lower()
+            if isinstance(v, (int, float)):
+                v = str(v)
+            if isinstance(v, dict):
+                v = json.dumps(v)
+
+            if k in collection_formats:
+                collection_format = collection_formats[k]
+                if collection_format == "multi":
+                    new_params.extend((k, str(value)) for value in v)
+                else:
+                    if collection_format == "ssv":
+                        delimiter = " "
+                    elif collection_format == "tsv":
+                        delimiter = "\t"
+                    elif collection_format == "pipes":
+                        delimiter = "|"
+                    else:  # csv is the default
+                        delimiter = ","
+                    new_params.append(
+                        (k, delimiter.join(quote(str(value)) for value in v))
+                    )
+            else:
+                new_params.append((k, quote(str(v))))
+
+        return "&".join(["=".join(map(str, item)) for item in new_params])
+
+    def files_parameters(
+        self,
+        files: Dict[str, Union[str, bytes, List[str], List[bytes], Tuple[str, bytes]]],
+    ):
+        """Builds form parameters.
+
+        :param files: File parameters.
+        :return: Form parameters with files.
+        """
+        params = []
+        for k, v in files.items():
+            if isinstance(v, str):
+                with open(v, "rb") as f:
+                    filename = os.path.basename(f.name)
+                    filedata = f.read()
+            elif isinstance(v, bytes):
+                filename = k
+                filedata = v
+            elif isinstance(v, tuple):
+                filename, filedata = v
+            elif isinstance(v, list):
+                for file_param in v:
+                    params.extend(self.files_parameters({k: file_param}))
+                continue
+            else:
+                raise ValueError("Unsupported file value")
+            mimetype = mimetypes.guess_type(filename)[0] or "application/octet-stream"
+            params.append(tuple([k, tuple([filename, filedata, mimetype])]))
+        return params
+
+    def select_header_accept(self, accepts: List[str]) -> Optional[str]:
+        """Returns `Accept` based on an array of accepts provided.
+
+        :param accepts: List of headers.
+        :return: Accept (e.g. application/json).
+        """
+        if not accepts:
+            return None
+
+        for accept in accepts:
+            if re.search("json", accept, re.IGNORECASE):
+                return accept
+
+        return accepts[0]
+
+    def select_header_content_type(self, content_types):
+        """Returns `Content-Type` based on an array of content_types provided.
+
+        :param content_types: List of content-types.
+        :return: Content-Type (e.g. application/json).
+        """
+        if not content_types:
+            return None
+
+        for content_type in content_types:
+            if re.search("json", content_type, re.IGNORECASE):
+                return content_type
+
+        return content_types[0]
+
+    def update_params_for_auth(
+        self,
+        headers,
+        queries,
+        auth_settings,
+        resource_path,
+        method,
+        body,
+        request_auth=None,
+    ) -> None:
+        """Updates header and query params based on authentication setting.
+
+        :param headers: Header parameters dict to be updated.
+        :param queries: Query parameters tuple list to be updated.
+        :param auth_settings: Authentication setting identifiers list.
+        :resource_path: A string representation of the HTTP request resource path.
+        :method: A string representation of the HTTP request method.
+        :body: A object representing the body of the HTTP request.
+        The object type is the return value of sanitize_for_serialization().
+        :param request_auth: if set, the provided settings will
+                             override the token in the configuration.
+        """
+        if not auth_settings:
+            return
+
+        if request_auth:
+            self._apply_auth_params(
+                headers, queries, resource_path, method, body, request_auth
+            )
+        else:
+            for auth in auth_settings:
+                auth_setting = self.configuration.auth_settings().get(auth)
+                if auth_setting:
+                    self._apply_auth_params(
+                        headers, queries, resource_path, method, body, auth_setting
+                    )
+
+    def _apply_auth_params(
+        self, headers, queries, resource_path, method, body, auth_setting
+    ) -> None:
+        """Updates the request parameters based on a single auth_setting
+
+        :param headers: Header parameters dict to be updated.
+        :param queries: Query parameters tuple list to be updated.
+        :resource_path: A string representation of the HTTP request resource path.
+        :method: A string representation of the HTTP request method.
+        :body: A object representing the body of the HTTP request.
+        The object type is the return value of sanitize_for_serialization().
+        :param auth_setting: auth settings for the endpoint
+        """
+        if auth_setting["in"] == "cookie":
+            headers["Cookie"] = auth_setting["value"]
+        elif auth_setting["in"] == "header":
+            if auth_setting["type"] != "http-signature":
+                headers[auth_setting["key"]] = auth_setting["value"]
+        elif auth_setting["in"] == "query":
+            queries.append((auth_setting["key"], auth_setting["value"]))
+        else:
+            raise ApiValueError("Authentication token must be in `query` or `header`")
+
+    def __deserialize_file(self, response):
+        """Deserializes body to file
+
+        Saves response body into a file in a temporary folder,
+        using the filename from the `Content-Disposition` header if provided.
+
+        handle file downloading
+        save response body into a tmp file and return the instance
+
+        :param response:  RESTResponse.
+        :return: file path.
+        """
+        fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path)
+        os.close(fd)
+        os.remove(path)
+
+        content_disposition = response.getheader("Content-Disposition")
+        if content_disposition:
+            m = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', content_disposition)
+            assert m is not None, "Unexpected 'content-disposition' header value"
+            filename = m.group(1)
+            path = os.path.join(os.path.dirname(path), filename)
+
+        with open(path, "wb") as f:
+            f.write(response.data)
+
+        return path
+
+    def __deserialize_primitive(self, data, klass):
+        """Deserializes string to primitive type.
+
+        :param data: str.
+        :param klass: class literal.
+
+        :return: int, long, float, str, bool.
+        """
+        try:
+            return klass(data)
+        except UnicodeEncodeError:
+            return str(data)
+        except TypeError:
+            return data
+
+    def __deserialize_object(self, value):
+        """Return an original value.
+
+        :return: object.
+        """
+        return value
+
+    def __deserialize_date(self, string):
+        """Deserializes string to date.
+
+        :param string: str.
+        :return: date.
+        """
+        try:
+            return parse(string).date()
+        except ImportError:
+            return string
+        except ValueError:
+            raise rest.ApiException(
+                status=0, reason="Failed to parse `{0}` as date object".format(string)
+            )
+
+    def __deserialize_datetime(self, string):
+        """Deserializes string to datetime.
+
+        The string should be in iso8601 datetime format.
+
+        :param string: str.
+        :return: datetime.
+        """
+        try:
+            return parse(string)
+        except ImportError:
+            return string
+        except ValueError:
+            raise rest.ApiException(
+                status=0,
+                reason=("Failed to parse `{0}` as datetime object".format(string)),
+            )
+
+    def __deserialize_enum(self, data, klass):
+        """Deserializes primitive type to enum.
+
+        :param data: primitive type.
+        :param klass: class literal.
+        :return: enum value.
+        """
+        try:
+            return klass(data)
+        except ValueError:
+            raise rest.ApiException(
+                status=0, reason=("Failed to parse `{0}` as `{1}`".format(data, klass))
+            )
+
+    def __deserialize_model(self, data, klass):
+        """Deserializes list or dict to model.
+
+        :param data: dict, list.
+        :param klass: class literal.
+        :return: model object.
+        """
+
+        return klass.from_dict(data)
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api_response.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api_response.py
new file mode 100644
index 00000000..ca801da0
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/api_response.py
@@ -0,0 +1,22 @@
+"""API response object."""
+
+from __future__ import annotations
+
+from typing import Generic, Mapping, Optional, TypeVar
+
+from pydantic import BaseModel, Field, StrictBytes, StrictInt
+
+T = TypeVar("T")
+
+
+class ApiResponse(BaseModel, Generic[T]):
+    """
+    API response object
+    """
+
+    status_code: StrictInt = Field(description="HTTP status code")
+    headers: Optional[Mapping[str, str]] = Field(None, description="HTTP headers")
+    data: T = Field(description="Deserialized data given the data type")
+    raw_data: StrictBytes = Field(description="Raw data (HTTP response body)")
+
+    model_config = {"arbitrary_types_allowed": True}
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/configuration.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/configuration.py
new file mode 100644
index 00000000..635209d2
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/configuration.py
@@ -0,0 +1,611 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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
+import http.client as httplib
+import logging
+import sys
+from logging import FileHandler
+from typing import Any, ClassVar, Dict, List, Literal, Optional, TypedDict
+
+import urllib3
+from typing_extensions import NotRequired, Self
+
+JSON_SCHEMA_VALIDATION_KEYWORDS = {
+    "multipleOf",
+    "maximum",
+    "exclusiveMaximum",
+    "minimum",
+    "exclusiveMinimum",
+    "maxLength",
+    "minLength",
+    "pattern",
+    "maxItems",
+    "minItems",
+}
+
+ServerVariablesT = Dict[str, str]
+
+GenericAuthSetting = TypedDict(
+    "GenericAuthSetting",
+    {
+        "type": str,
+        "in": str,
+        "key": str,
+        "value": str,
+    },
+)
+
+
+OAuth2AuthSetting = TypedDict(
+    "OAuth2AuthSetting",
+    {
+        "type": Literal["oauth2"],
+        "in": Literal["header"],
+        "key": Literal["Authorization"],
+        "value": str,
+    },
+)
+
+
+APIKeyAuthSetting = TypedDict(
+    "APIKeyAuthSetting",
+    {
+        "type": Literal["api_key"],
+        "in": str,
+        "key": str,
+        "value": Optional[str],
+    },
+)
+
+
+BasicAuthSetting = TypedDict(
+    "BasicAuthSetting",
+    {
+        "type": Literal["basic"],
+        "in": Literal["header"],
+        "key": Literal["Authorization"],
+        "value": Optional[str],
+    },
+)
+
+
+BearerFormatAuthSetting = TypedDict(
+    "BearerFormatAuthSetting",
+    {
+        "type": Literal["bearer"],
+        "in": Literal["header"],
+        "format": Literal["JWT"],
+        "key": Literal["Authorization"],
+        "value": str,
+    },
+)
+
+
+BearerAuthSetting = TypedDict(
+    "BearerAuthSetting",
+    {
+        "type": Literal["bearer"],
+        "in": Literal["header"],
+        "key": Literal["Authorization"],
+        "value": str,
+    },
+)
+
+
+HTTPSignatureAuthSetting = TypedDict(
+    "HTTPSignatureAuthSetting",
+    {
+        "type": Literal["http-signature"],
+        "in": Literal["header"],
+        "key": Literal["Authorization"],
+        "value": None,
+    },
+)
+
+
+AuthSettings = TypedDict(
+    "AuthSettings",
+    {
+        "bearerAuth": BearerAuthSetting,
+        "cookieAuth": APIKeyAuthSetting,
+    },
+    total=False,
+)
+
+
+class HostSettingVariable(TypedDict):
+    description: str
+    default_value: str
+    enum_values: List[str]
+
+
+class HostSetting(TypedDict):
+    url: str
+    description: str
+    variables: NotRequired[Dict[str, HostSettingVariable]]
+
+
+class Configuration:
+    """This class contains various settings of the API client.
+
+        :param host: Base url.
+        :param ignore_operation_servers
+          Boolean to ignore operation servers for the API client.
+          Config will use `host` as the base url regardless of the operation servers.
+        :param api_key: Dict to store API key(s).
+          Each entry in the dict specifies an API key.
+          The dict key is the name of the security scheme in the OAS specification.
+          The dict value is the API key secret.
+        :param api_key_prefix: Dict to store API prefix (e.g. Bearer).
+          The dict key is the name of the security scheme in the OAS specification.
+          The dict value is an API key prefix when generating the auth data.
+        :param username: Username for HTTP basic authentication.
+        :param password: Password for HTTP basic authentication.
+        :param access_token: Access token.
+        :param server_index: Index to servers configuration.
+        :param server_variables: Mapping with string values to replace variables in
+          templated server configuration. The validation of enums is performed for
+          variables with defined enum values before.
+        :param server_operation_index: Mapping from operation ID to an index to server
+          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.
+        :param ssl_ca_cert: str - the path to a file of concatenated CA certificates
+          in PEM format.
+        :param retries: Number of retries for API requests.
+
+        :Example:
+
+        API Key Authentication Example.
+        Given the following security scheme in the OpenAPI specification:
+          components:
+            securitySchemes:
+              cookieAuth:         # name for the security scheme
+                type: apiKey
+                in: cookie
+                name: JSESSIONID  # cookie name
+
+        You can programmatically set the cookie:
+
+    conf = hatchet_sdk.clients.rest.Configuration(
+        api_key={'cookieAuth': 'abc123'}
+        api_key_prefix={'cookieAuth': 'JSESSIONID'}
+    )
+
+        The following cookie will be added to the HTTP request:
+           Cookie: JSESSIONID abc123
+    """
+
+    _default: ClassVar[Optional[Self]] = None
+
+    def __init__(
+        self,
+        host: Optional[str] = None,
+        api_key: Optional[Dict[str, str]] = None,
+        api_key_prefix: Optional[Dict[str, str]] = None,
+        username: Optional[str] = None,
+        password: Optional[str] = None,
+        access_token: Optional[str] = None,
+        server_index: Optional[int] = None,
+        server_variables: Optional[ServerVariablesT] = None,
+        server_operation_index: Optional[Dict[int, int]] = None,
+        server_operation_variables: Optional[Dict[int, ServerVariablesT]] = None,
+        ignore_operation_servers: bool = False,
+        ssl_ca_cert: Optional[str] = None,
+        retries: Optional[int] = None,
+        *,
+        debug: Optional[bool] = None,
+    ) -> None:
+        """Constructor"""
+        self._base_path = "http://localhost" if host is None else host
+        """Default Base url
+        """
+        self.server_index = 0 if server_index is None and host is None else server_index
+        self.server_operation_index = server_operation_index or {}
+        """Default server index
+        """
+        self.server_variables = server_variables or {}
+        self.server_operation_variables = server_operation_variables or {}
+        """Default server variables
+        """
+        self.ignore_operation_servers = ignore_operation_servers
+        """Ignore operation servers
+        """
+        self.temp_folder_path = None
+        """Temp file folder for downloading files
+        """
+        # Authentication Settings
+        self.api_key = {}
+        if api_key:
+            self.api_key = api_key
+        """dict to store API key(s)
+        """
+        self.api_key_prefix = {}
+        if api_key_prefix:
+            self.api_key_prefix = api_key_prefix
+        """dict to store API prefix (e.g. Bearer)
+        """
+        self.refresh_api_key_hook = None
+        """function hook to refresh API key if expired
+        """
+        self.username = username
+        """Username for HTTP basic authentication
+        """
+        self.password = password
+        """Password for HTTP basic authentication
+        """
+        self.access_token = access_token
+        """Access token
+        """
+        self.logger = {}
+        """Logging Settings
+        """
+        self.logger["package_logger"] = logging.getLogger("hatchet_sdk.clients.rest")
+        self.logger["urllib3_logger"] = logging.getLogger("urllib3")
+        self.logger_format = "%(asctime)s %(levelname)s %(message)s"
+        """Log format
+        """
+        self.logger_stream_handler = None
+        """Log stream handler
+        """
+        self.logger_file_handler: Optional[FileHandler] = None
+        """Log file handler
+        """
+        self.logger_file = None
+        """Debug file location
+        """
+        if debug is not None:
+            self.debug = debug
+        else:
+            self.__debug = False
+        """Debug switch
+        """
+
+        self.verify_ssl = True
+        """SSL/TLS verification
+           Set this to false to skip verifying SSL certificate when calling API
+           from https server.
+        """
+        self.ssl_ca_cert = ssl_ca_cert
+        """Set this to customize the certificate file to verify the peer.
+        """
+        self.cert_file = None
+        """client certificate file
+        """
+        self.key_file = None
+        """client key file
+        """
+        self.assert_hostname = None
+        """Set this to True/False to enable/disable SSL hostname verification.
+        """
+        self.tls_server_name = None
+        """SSL/TLS Server Name Indication (SNI)
+           Set this to the SNI value expected by the server.
+        """
+
+        self.connection_pool_maxsize = 100
+        """This value is passed to the aiohttp to limit simultaneous connections.
+           Default values is 100, None means no-limit.
+        """
+
+        self.proxy: Optional[str] = None
+        """Proxy URL
+        """
+        self.proxy_headers = None
+        """Proxy headers
+        """
+        self.safe_chars_for_path_param = ""
+        """Safe chars for path_param
+        """
+        self.retries = retries
+        """Adding retries to override urllib3 default value 3
+        """
+        # Enable client side validation
+        self.client_side_validation = True
+
+        self.socket_options = None
+        """Options to pass down to the underlying urllib3 socket
+        """
+
+        self.datetime_format = "%Y-%m-%dT%H:%M:%S.%f%z"
+        """datetime format
+        """
+
+        self.date_format = "%Y-%m-%d"
+        """date format
+        """
+
+    def __deepcopy__(self, memo: Dict[int, Any]) -> Self:
+        cls = self.__class__
+        result = cls.__new__(cls)
+        memo[id(self)] = result
+        for k, v in self.__dict__.items():
+            if k not in ("logger", "logger_file_handler"):
+                setattr(result, k, copy.deepcopy(v, memo))
+        # shallow copy of loggers
+        result.logger = copy.copy(self.logger)
+        # use setters to configure loggers
+        result.logger_file = self.logger_file
+        result.debug = self.debug
+        return result
+
+    def __setattr__(self, name: str, value: Any) -> None:
+        object.__setattr__(self, name, value)
+
+    @classmethod
+    def set_default(cls, default: Optional[Self]) -> None:
+        """Set default instance of configuration.
+
+        It stores default configuration, which can be
+        returned by get_default_copy method.
+
+        :param default: object of Configuration
+        """
+        cls._default = default
+
+    @classmethod
+    def get_default_copy(cls) -> Self:
+        """Deprecated. Please use `get_default` instead.
+
+        Deprecated. Please use `get_default` instead.
+
+        :return: The configuration object.
+        """
+        return cls.get_default()
+
+    @classmethod
+    def get_default(cls) -> Self:
+        """Return the default configuration.
+
+        This method returns newly created, based on default constructor,
+        object of Configuration class or returns a copy of default
+        configuration.
+
+        :return: The configuration object.
+        """
+        if cls._default is None:
+            cls._default = cls()
+        return cls._default
+
+    @property
+    def logger_file(self) -> Optional[str]:
+        """The logger file.
+
+        If the logger_file is None, then add stream handler and remove file
+        handler. Otherwise, add file handler and remove stream handler.
+
+        :param value: The logger_file path.
+        :type: str
+        """
+        return self.__logger_file
+
+    @logger_file.setter
+    def logger_file(self, value: Optional[str]) -> None:
+        """The logger file.
+
+        If the logger_file is None, then add stream handler and remove file
+        handler. Otherwise, add file handler and remove stream handler.
+
+        :param value: The logger_file path.
+        :type: str
+        """
+        self.__logger_file = value
+        if self.__logger_file:
+            # If set logging file,
+            # then add file handler and remove stream handler.
+            self.logger_file_handler = logging.FileHandler(self.__logger_file)
+            self.logger_file_handler.setFormatter(self.logger_formatter)
+            for _, logger in self.logger.items():
+                logger.addHandler(self.logger_file_handler)
+
+    @property
+    def debug(self) -> bool:
+        """Debug status
+
+        :param value: The debug status, True or False.
+        :type: bool
+        """
+        return self.__debug
+
+    @debug.setter
+    def debug(self, value: bool) -> None:
+        """Debug status
+
+        :param value: The debug status, True or False.
+        :type: bool
+        """
+        self.__debug = value
+        if self.__debug:
+            # if debug status is True, turn on debug logging
+            for _, logger in self.logger.items():
+                logger.setLevel(logging.DEBUG)
+            # turn on httplib debug
+            httplib.HTTPConnection.debuglevel = 1
+        else:
+            # if debug status is False, turn off debug logging,
+            # setting log level to default `logging.WARNING`
+            for _, logger in self.logger.items():
+                logger.setLevel(logging.WARNING)
+            # turn off httplib debug
+            httplib.HTTPConnection.debuglevel = 0
+
+    @property
+    def logger_format(self) -> str:
+        """The logger format.
+
+        The logger_formatter will be updated when sets logger_format.
+
+        :param value: The format string.
+        :type: str
+        """
+        return self.__logger_format
+
+    @logger_format.setter
+    def logger_format(self, value: str) -> None:
+        """The logger format.
+
+        The logger_formatter will be updated when sets logger_format.
+
+        :param value: The format string.
+        :type: str
+        """
+        self.__logger_format = value
+        self.logger_formatter = logging.Formatter(self.__logger_format)
+
+    def get_api_key_with_prefix(
+        self, identifier: str, alias: Optional[str] = None
+    ) -> Optional[str]:
+        """Gets API key (with prefix if set).
+
+        :param identifier: The identifier of apiKey.
+        :param alias: The alternative identifier of apiKey.
+        :return: The token for api key authentication.
+        """
+        if self.refresh_api_key_hook is not None:
+            self.refresh_api_key_hook(self)
+        key = self.api_key.get(
+            identifier, self.api_key.get(alias) if alias is not None else None
+        )
+        if key:
+            prefix = self.api_key_prefix.get(identifier)
+            if prefix:
+                return "%s %s" % (prefix, key)
+            else:
+                return key
+
+        return None
+
+    def get_basic_auth_token(self) -> Optional[str]:
+        """Gets HTTP basic authentication header (string).
+
+        :return: The token for basic HTTP authentication.
+        """
+        username = ""
+        if self.username is not None:
+            username = self.username
+        password = ""
+        if self.password is not None:
+            password = self.password
+        return urllib3.util.make_headers(basic_auth=username + ":" + password).get(
+            "authorization"
+        )
+
+    def auth_settings(self) -> AuthSettings:
+        """Gets Auth Settings dict for api client.
+
+        :return: The Auth Settings information dict.
+        """
+        auth: AuthSettings = {}
+        if self.access_token is not None:
+            auth["bearerAuth"] = {
+                "type": "bearer",
+                "in": "header",
+                "key": "Authorization",
+                "value": "Bearer " + self.access_token,
+            }
+        if "cookieAuth" in self.api_key:
+            auth["cookieAuth"] = {
+                "type": "api_key",
+                "in": "cookie",
+                "key": "hatchet",
+                "value": self.get_api_key_with_prefix(
+                    "cookieAuth",
+                ),
+            }
+        return auth
+
+    def to_debug_report(self) -> str:
+        """Gets the essential information for debugging.
+
+        :return: The report for debugging.
+        """
+        return (
+            "Python SDK Debug Report:\n"
+            "OS: {env}\n"
+            "Python Version: {pyversion}\n"
+            "Version of the API: 1.0.0\n"
+            "SDK Package Version: 1.0.0".format(env=sys.platform, pyversion=sys.version)
+        )
+
+    def get_host_settings(self) -> List[HostSetting]:
+        """Gets an array of host settings
+
+        :return: An array of host settings
+        """
+        return [
+            {
+                "url": "",
+                "description": "No description provided",
+            }
+        ]
+
+    def get_host_from_settings(
+        self,
+        index: Optional[int],
+        variables: Optional[ServerVariablesT] = None,
+        servers: Optional[List[HostSetting]] = None,
+    ) -> str:
+        """Gets host URL based on the index and variables
+        :param index: array index of the host settings
+        :param variables: hash of variable and the corresponding value
+        :param servers: an array of host settings or None
+        :return: URL based on host settings
+        """
+        if index is None:
+            return self._base_path
+
+        variables = {} if variables is None else variables
+        servers = self.get_host_settings() if servers is None else servers
+
+        try:
+            server = servers[index]
+        except IndexError:
+            raise ValueError(
+                "Invalid index {0} when selecting the host settings. "
+                "Must be less than {1}".format(index, len(servers))
+            )
+
+        url = server["url"]
+
+        # go through variables and replace placeholders
+        for variable_name, variable in server.get("variables", {}).items():
+            used_value = variables.get(variable_name, variable["default_value"])
+
+            if "enum_values" in variable and used_value not in variable["enum_values"]:
+                raise ValueError(
+                    "The variable `{0}` in the host URL has invalid value "
+                    "{1}. Must be {2}.".format(
+                        variable_name, variables[variable_name], variable["enum_values"]
+                    )
+                )
+
+            url = url.replace("{" + variable_name + "}", used_value)
+
+        return url
+
+    @property
+    def host(self) -> str:
+        """Return generated host."""
+        return self.get_host_from_settings(
+            self.server_index, variables=self.server_variables
+        )
+
+    @host.setter
+    def host(self, value: str) -> None:
+        """Fix base path."""
+        self._base_path = value
+        self.server_index = None
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/exceptions.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/exceptions.py
new file mode 100644
index 00000000..b41ac1d2
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/exceptions.py
@@ -0,0 +1,200 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 typing import Any, Optional
+
+from typing_extensions import Self
+
+
+class OpenApiException(Exception):
+    """The base exception class for all OpenAPIExceptions"""
+
+
+class ApiTypeError(OpenApiException, TypeError):
+    def __init__(
+        self, msg, path_to_item=None, valid_classes=None, key_type=None
+    ) -> None:
+        """Raises an exception for TypeErrors
+
+        Args:
+            msg (str): the exception message
+
+        Keyword Args:
+            path_to_item (list): a list of keys an indices to get to the
+                                 current_item
+                                 None if unset
+            valid_classes (tuple): the primitive classes that current item
+                                   should be an instance of
+                                   None if unset
+            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 list
+                             None if unset
+        """
+        self.path_to_item = path_to_item
+        self.valid_classes = valid_classes
+        self.key_type = key_type
+        full_msg = msg
+        if path_to_item:
+            full_msg = "{0} at {1}".format(msg, render_path(path_to_item))
+        super(ApiTypeError, self).__init__(full_msg)
+
+
+class ApiValueError(OpenApiException, ValueError):
+    def __init__(self, msg, path_to_item=None) -> None:
+        """
+        Args:
+            msg (str): the exception message
+
+        Keyword Args:
+            path_to_item (list) the path to the exception in the
+                received_data dict. None if unset
+        """
+
+        self.path_to_item = path_to_item
+        full_msg = msg
+        if path_to_item:
+            full_msg = "{0} at {1}".format(msg, render_path(path_to_item))
+        super(ApiValueError, self).__init__(full_msg)
+
+
+class ApiAttributeError(OpenApiException, AttributeError):
+    def __init__(self, msg, path_to_item=None) -> None:
+        """
+        Raised when an attribute reference or assignment fails.
+
+        Args:
+            msg (str): the exception message
+
+        Keyword Args:
+            path_to_item (None/list) the path to the exception in the
+                received_data dict
+        """
+        self.path_to_item = path_to_item
+        full_msg = msg
+        if path_to_item:
+            full_msg = "{0} at {1}".format(msg, render_path(path_to_item))
+        super(ApiAttributeError, self).__init__(full_msg)
+
+
+class ApiKeyError(OpenApiException, KeyError):
+    def __init__(self, msg, path_to_item=None) -> None:
+        """
+        Args:
+            msg (str): the exception message
+
+        Keyword Args:
+            path_to_item (None/list) the path to the exception in the
+                received_data dict
+        """
+        self.path_to_item = path_to_item
+        full_msg = msg
+        if path_to_item:
+            full_msg = "{0} at {1}".format(msg, render_path(path_to_item))
+        super(ApiKeyError, self).__init__(full_msg)
+
+
+class ApiException(OpenApiException):
+
+    def __init__(
+        self,
+        status=None,
+        reason=None,
+        http_resp=None,
+        *,
+        body: Optional[str] = None,
+        data: Optional[Any] = None,
+    ) -> None:
+        self.status = status
+        self.reason = reason
+        self.body = body
+        self.data = data
+        self.headers = None
+
+        if http_resp:
+            if self.status is None:
+                self.status = http_resp.status
+            if self.reason is None:
+                self.reason = http_resp.reason
+            if self.body is None:
+                try:
+                    self.body = http_resp.data.decode("utf-8")
+                except Exception:
+                    pass
+            self.headers = http_resp.getheaders()
+
+    @classmethod
+    def from_response(
+        cls,
+        *,
+        http_resp,
+        body: Optional[str],
+        data: Optional[Any],
+    ) -> Self:
+        if http_resp.status == 400:
+            raise BadRequestException(http_resp=http_resp, body=body, data=data)
+
+        if http_resp.status == 401:
+            raise UnauthorizedException(http_resp=http_resp, body=body, data=data)
+
+        if http_resp.status == 403:
+            raise ForbiddenException(http_resp=http_resp, body=body, data=data)
+
+        if http_resp.status == 404:
+            raise NotFoundException(http_resp=http_resp, body=body, data=data)
+
+        if 500 <= http_resp.status <= 599:
+            raise ServiceException(http_resp=http_resp, body=body, data=data)
+        raise ApiException(http_resp=http_resp, body=body, data=data)
+
+    def __str__(self):
+        """Custom error messages for exception"""
+        error_message = "({0})\n" "Reason: {1}\n".format(self.status, self.reason)
+        if self.headers:
+            error_message += "HTTP response headers: {0}\n".format(self.headers)
+
+        if self.data or self.body:
+            error_message += "HTTP response body: {0}\n".format(self.data or self.body)
+
+        return error_message
+
+
+class BadRequestException(ApiException):
+    pass
+
+
+class NotFoundException(ApiException):
+    pass
+
+
+class UnauthorizedException(ApiException):
+    pass
+
+
+class ForbiddenException(ApiException):
+    pass
+
+
+class ServiceException(ApiException):
+    pass
+
+
+def render_path(path_to_item):
+    """Returns a string representation of a path"""
+    result = ""
+    for pth in path_to_item:
+        if isinstance(pth, int):
+            result += "[{0}]".format(pth)
+        else:
+            result += "['{0}']".format(pth)
+    return result
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/__init__.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/__init__.py
new file mode 100644
index 00000000..386c4c03
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/__init__.py
@@ -0,0 +1,260 @@
+# coding: utf-8
+
+# flake8: noqa
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 hatchet_sdk.clients.rest.models.accept_invite_request import AcceptInviteRequest
+
+# import models into model package
+from hatchet_sdk.clients.rest.models.api_error import APIError
+from hatchet_sdk.clients.rest.models.api_errors import APIErrors
+from hatchet_sdk.clients.rest.models.api_meta import APIMeta
+from hatchet_sdk.clients.rest.models.api_meta_auth import APIMetaAuth
+from hatchet_sdk.clients.rest.models.api_meta_integration import APIMetaIntegration
+from hatchet_sdk.clients.rest.models.api_meta_posthog import APIMetaPosthog
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.api_token import APIToken
+from hatchet_sdk.clients.rest.models.bulk_create_event_request import (
+    BulkCreateEventRequest,
+)
+from hatchet_sdk.clients.rest.models.cancel_event_request import CancelEventRequest
+from hatchet_sdk.clients.rest.models.concurrency_limit_strategy import (
+    ConcurrencyLimitStrategy,
+)
+from hatchet_sdk.clients.rest.models.create_api_token_request import (
+    CreateAPITokenRequest,
+)
+from hatchet_sdk.clients.rest.models.create_api_token_response import (
+    CreateAPITokenResponse,
+)
+from hatchet_sdk.clients.rest.models.create_cron_workflow_trigger_request import (
+    CreateCronWorkflowTriggerRequest,
+)
+from hatchet_sdk.clients.rest.models.create_event_request import CreateEventRequest
+from hatchet_sdk.clients.rest.models.create_pull_request_from_step_run import (
+    CreatePullRequestFromStepRun,
+)
+from hatchet_sdk.clients.rest.models.create_sns_integration_request import (
+    CreateSNSIntegrationRequest,
+)
+from hatchet_sdk.clients.rest.models.create_tenant_alert_email_group_request import (
+    CreateTenantAlertEmailGroupRequest,
+)
+from hatchet_sdk.clients.rest.models.create_tenant_invite_request import (
+    CreateTenantInviteRequest,
+)
+from hatchet_sdk.clients.rest.models.create_tenant_request import CreateTenantRequest
+from hatchet_sdk.clients.rest.models.cron_workflows import CronWorkflows
+from hatchet_sdk.clients.rest.models.cron_workflows_list import CronWorkflowsList
+from hatchet_sdk.clients.rest.models.cron_workflows_method import CronWorkflowsMethod
+from hatchet_sdk.clients.rest.models.cron_workflows_order_by_field import (
+    CronWorkflowsOrderByField,
+)
+from hatchet_sdk.clients.rest.models.event import Event
+from hatchet_sdk.clients.rest.models.event_data import EventData
+from hatchet_sdk.clients.rest.models.event_key_list import EventKeyList
+from hatchet_sdk.clients.rest.models.event_list import EventList
+from hatchet_sdk.clients.rest.models.event_order_by_direction import (
+    EventOrderByDirection,
+)
+from hatchet_sdk.clients.rest.models.event_order_by_field import EventOrderByField
+from hatchet_sdk.clients.rest.models.event_update_cancel200_response import (
+    EventUpdateCancel200Response,
+)
+from hatchet_sdk.clients.rest.models.event_workflow_run_summary import (
+    EventWorkflowRunSummary,
+)
+from hatchet_sdk.clients.rest.models.events import Events
+from hatchet_sdk.clients.rest.models.get_step_run_diff_response import (
+    GetStepRunDiffResponse,
+)
+from hatchet_sdk.clients.rest.models.info_get_version200_response import (
+    InfoGetVersion200Response,
+)
+from hatchet_sdk.clients.rest.models.job import Job
+from hatchet_sdk.clients.rest.models.job_run import JobRun
+from hatchet_sdk.clients.rest.models.job_run_status import JobRunStatus
+from hatchet_sdk.clients.rest.models.list_api_tokens_response import (
+    ListAPITokensResponse,
+)
+from hatchet_sdk.clients.rest.models.list_pull_requests_response import (
+    ListPullRequestsResponse,
+)
+from hatchet_sdk.clients.rest.models.list_slack_webhooks import ListSlackWebhooks
+from hatchet_sdk.clients.rest.models.list_sns_integrations import ListSNSIntegrations
+from hatchet_sdk.clients.rest.models.log_line import LogLine
+from hatchet_sdk.clients.rest.models.log_line_level import LogLineLevel
+from hatchet_sdk.clients.rest.models.log_line_list import LogLineList
+from hatchet_sdk.clients.rest.models.log_line_order_by_direction import (
+    LogLineOrderByDirection,
+)
+from hatchet_sdk.clients.rest.models.log_line_order_by_field import LogLineOrderByField
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.pull_request import PullRequest
+from hatchet_sdk.clients.rest.models.pull_request_state import PullRequestState
+from hatchet_sdk.clients.rest.models.queue_metrics import QueueMetrics
+from hatchet_sdk.clients.rest.models.rate_limit import RateLimit
+from hatchet_sdk.clients.rest.models.rate_limit_list import RateLimitList
+from hatchet_sdk.clients.rest.models.rate_limit_order_by_direction import (
+    RateLimitOrderByDirection,
+)
+from hatchet_sdk.clients.rest.models.rate_limit_order_by_field import (
+    RateLimitOrderByField,
+)
+from hatchet_sdk.clients.rest.models.recent_step_runs import RecentStepRuns
+from hatchet_sdk.clients.rest.models.reject_invite_request import RejectInviteRequest
+from hatchet_sdk.clients.rest.models.replay_event_request import ReplayEventRequest
+from hatchet_sdk.clients.rest.models.replay_workflow_runs_request import (
+    ReplayWorkflowRunsRequest,
+)
+from hatchet_sdk.clients.rest.models.replay_workflow_runs_response import (
+    ReplayWorkflowRunsResponse,
+)
+from hatchet_sdk.clients.rest.models.rerun_step_run_request import RerunStepRunRequest
+from hatchet_sdk.clients.rest.models.schedule_workflow_run_request import (
+    ScheduleWorkflowRunRequest,
+)
+from hatchet_sdk.clients.rest.models.scheduled_run_status import ScheduledRunStatus
+from hatchet_sdk.clients.rest.models.scheduled_workflows import ScheduledWorkflows
+from hatchet_sdk.clients.rest.models.scheduled_workflows_list import (
+    ScheduledWorkflowsList,
+)
+from hatchet_sdk.clients.rest.models.scheduled_workflows_method import (
+    ScheduledWorkflowsMethod,
+)
+from hatchet_sdk.clients.rest.models.scheduled_workflows_order_by_field import (
+    ScheduledWorkflowsOrderByField,
+)
+from hatchet_sdk.clients.rest.models.semaphore_slots import SemaphoreSlots
+from hatchet_sdk.clients.rest.models.slack_webhook import SlackWebhook
+from hatchet_sdk.clients.rest.models.sns_integration import SNSIntegration
+from hatchet_sdk.clients.rest.models.step import Step
+from hatchet_sdk.clients.rest.models.step_run import StepRun
+from hatchet_sdk.clients.rest.models.step_run_archive import StepRunArchive
+from hatchet_sdk.clients.rest.models.step_run_archive_list import StepRunArchiveList
+from hatchet_sdk.clients.rest.models.step_run_diff import StepRunDiff
+from hatchet_sdk.clients.rest.models.step_run_event import StepRunEvent
+from hatchet_sdk.clients.rest.models.step_run_event_list import StepRunEventList
+from hatchet_sdk.clients.rest.models.step_run_event_reason import StepRunEventReason
+from hatchet_sdk.clients.rest.models.step_run_event_severity import StepRunEventSeverity
+from hatchet_sdk.clients.rest.models.step_run_status import StepRunStatus
+from hatchet_sdk.clients.rest.models.tenant import Tenant
+from hatchet_sdk.clients.rest.models.tenant_alert_email_group import (
+    TenantAlertEmailGroup,
+)
+from hatchet_sdk.clients.rest.models.tenant_alert_email_group_list import (
+    TenantAlertEmailGroupList,
+)
+from hatchet_sdk.clients.rest.models.tenant_alerting_settings import (
+    TenantAlertingSettings,
+)
+from hatchet_sdk.clients.rest.models.tenant_invite import TenantInvite
+from hatchet_sdk.clients.rest.models.tenant_invite_list import TenantInviteList
+from hatchet_sdk.clients.rest.models.tenant_list import TenantList
+from hatchet_sdk.clients.rest.models.tenant_member import TenantMember
+from hatchet_sdk.clients.rest.models.tenant_member_list import TenantMemberList
+from hatchet_sdk.clients.rest.models.tenant_member_role import TenantMemberRole
+from hatchet_sdk.clients.rest.models.tenant_queue_metrics import TenantQueueMetrics
+from hatchet_sdk.clients.rest.models.tenant_resource import TenantResource
+from hatchet_sdk.clients.rest.models.tenant_resource_limit import TenantResourceLimit
+from hatchet_sdk.clients.rest.models.tenant_resource_policy import TenantResourcePolicy
+from hatchet_sdk.clients.rest.models.tenant_step_run_queue_metrics import (
+    TenantStepRunQueueMetrics,
+)
+from hatchet_sdk.clients.rest.models.trigger_workflow_run_request import (
+    TriggerWorkflowRunRequest,
+)
+from hatchet_sdk.clients.rest.models.update_tenant_alert_email_group_request import (
+    UpdateTenantAlertEmailGroupRequest,
+)
+from hatchet_sdk.clients.rest.models.update_tenant_invite_request import (
+    UpdateTenantInviteRequest,
+)
+from hatchet_sdk.clients.rest.models.update_tenant_request import UpdateTenantRequest
+from hatchet_sdk.clients.rest.models.update_worker_request import UpdateWorkerRequest
+from hatchet_sdk.clients.rest.models.user import User
+from hatchet_sdk.clients.rest.models.user_change_password_request import (
+    UserChangePasswordRequest,
+)
+from hatchet_sdk.clients.rest.models.user_login_request import UserLoginRequest
+from hatchet_sdk.clients.rest.models.user_register_request import UserRegisterRequest
+from hatchet_sdk.clients.rest.models.user_tenant_memberships_list import (
+    UserTenantMembershipsList,
+)
+from hatchet_sdk.clients.rest.models.user_tenant_public import UserTenantPublic
+from hatchet_sdk.clients.rest.models.webhook_worker import WebhookWorker
+from hatchet_sdk.clients.rest.models.webhook_worker_create_request import (
+    WebhookWorkerCreateRequest,
+)
+from hatchet_sdk.clients.rest.models.webhook_worker_create_response import (
+    WebhookWorkerCreateResponse,
+)
+from hatchet_sdk.clients.rest.models.webhook_worker_created import WebhookWorkerCreated
+from hatchet_sdk.clients.rest.models.webhook_worker_list_response import (
+    WebhookWorkerListResponse,
+)
+from hatchet_sdk.clients.rest.models.webhook_worker_request import WebhookWorkerRequest
+from hatchet_sdk.clients.rest.models.webhook_worker_request_list_response import (
+    WebhookWorkerRequestListResponse,
+)
+from hatchet_sdk.clients.rest.models.webhook_worker_request_method import (
+    WebhookWorkerRequestMethod,
+)
+from hatchet_sdk.clients.rest.models.worker import Worker
+from hatchet_sdk.clients.rest.models.worker_label import WorkerLabel
+from hatchet_sdk.clients.rest.models.worker_list import WorkerList
+from hatchet_sdk.clients.rest.models.worker_runtime_info import WorkerRuntimeInfo
+from hatchet_sdk.clients.rest.models.worker_runtime_sdks import WorkerRuntimeSDKs
+from hatchet_sdk.clients.rest.models.worker_type import WorkerType
+from hatchet_sdk.clients.rest.models.workflow import Workflow
+from hatchet_sdk.clients.rest.models.workflow_concurrency import WorkflowConcurrency
+from hatchet_sdk.clients.rest.models.workflow_kind import WorkflowKind
+from hatchet_sdk.clients.rest.models.workflow_list import WorkflowList
+from hatchet_sdk.clients.rest.models.workflow_metrics import WorkflowMetrics
+from hatchet_sdk.clients.rest.models.workflow_run import WorkflowRun
+from hatchet_sdk.clients.rest.models.workflow_run_list import WorkflowRunList
+from hatchet_sdk.clients.rest.models.workflow_run_order_by_direction import (
+    WorkflowRunOrderByDirection,
+)
+from hatchet_sdk.clients.rest.models.workflow_run_order_by_field import (
+    WorkflowRunOrderByField,
+)
+from hatchet_sdk.clients.rest.models.workflow_run_shape import WorkflowRunShape
+from hatchet_sdk.clients.rest.models.workflow_run_status import WorkflowRunStatus
+from hatchet_sdk.clients.rest.models.workflow_run_triggered_by import (
+    WorkflowRunTriggeredBy,
+)
+from hatchet_sdk.clients.rest.models.workflow_runs_cancel_request import (
+    WorkflowRunsCancelRequest,
+)
+from hatchet_sdk.clients.rest.models.workflow_runs_metrics import WorkflowRunsMetrics
+from hatchet_sdk.clients.rest.models.workflow_runs_metrics_counts import (
+    WorkflowRunsMetricsCounts,
+)
+from hatchet_sdk.clients.rest.models.workflow_tag import WorkflowTag
+from hatchet_sdk.clients.rest.models.workflow_trigger_cron_ref import (
+    WorkflowTriggerCronRef,
+)
+from hatchet_sdk.clients.rest.models.workflow_trigger_event_ref import (
+    WorkflowTriggerEventRef,
+)
+from hatchet_sdk.clients.rest.models.workflow_triggers import WorkflowTriggers
+from hatchet_sdk.clients.rest.models.workflow_update_request import (
+    WorkflowUpdateRequest,
+)
+from hatchet_sdk.clients.rest.models.workflow_version import WorkflowVersion
+from hatchet_sdk.clients.rest.models.workflow_version_definition import (
+    WorkflowVersionDefinition,
+)
+from hatchet_sdk.clients.rest.models.workflow_version_meta import WorkflowVersionMeta
+from hatchet_sdk.clients.rest.models.workflow_workers_count import WorkflowWorkersCount
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/accept_invite_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/accept_invite_request.py
new file mode 100644
index 00000000..241bff8a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/accept_invite_request.py
@@ -0,0 +1,83 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Annotated, Self
+
+
+class AcceptInviteRequest(BaseModel):
+    """
+    AcceptInviteRequest
+    """  # noqa: E501
+
+    invite: Annotated[str, Field(min_length=36, strict=True, max_length=36)]
+    __properties: ClassVar[List[str]] = ["invite"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of AcceptInviteRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of AcceptInviteRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"invite": obj.get("invite")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_error.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_error.py
new file mode 100644
index 00000000..64edc80f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_error.py
@@ -0,0 +1,102 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
+from typing_extensions import Self
+
+
+class APIError(BaseModel):
+    """
+    APIError
+    """  # noqa: E501
+
+    code: Optional[StrictInt] = Field(
+        default=None, description="a custom Hatchet error code"
+    )
+    var_field: Optional[StrictStr] = Field(
+        default=None,
+        description="the field that this error is associated with, if applicable",
+        alias="field",
+    )
+    description: StrictStr = Field(description="a description for this error")
+    docs_link: Optional[StrictStr] = Field(
+        default=None,
+        description="a link to the documentation for this error, if it exists",
+    )
+    __properties: ClassVar[List[str]] = ["code", "field", "description", "docs_link"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of APIError from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of APIError from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "code": obj.get("code"),
+                "field": obj.get("field"),
+                "description": obj.get("description"),
+                "docs_link": obj.get("docs_link"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_errors.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_errors.py
new file mode 100644
index 00000000..e4dfed11
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_errors.py
@@ -0,0 +1,100 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_error import APIError
+
+
+class APIErrors(BaseModel):
+    """
+    APIErrors
+    """  # noqa: E501
+
+    errors: List[APIError]
+    __properties: ClassVar[List[str]] = ["errors"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of APIErrors from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of each item in errors (list)
+        _items = []
+        if self.errors:
+            for _item_errors in self.errors:
+                if _item_errors:
+                    _items.append(_item_errors.to_dict())
+            _dict["errors"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of APIErrors from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "errors": (
+                    [APIError.from_dict(_item) for _item in obj["errors"]]
+                    if obj.get("errors") is not None
+                    else None
+                )
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_meta.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_meta.py
new file mode 100644
index 00000000..93c17f05
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_meta.py
@@ -0,0 +1,144 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_meta_auth import APIMetaAuth
+from hatchet_sdk.clients.rest.models.api_meta_posthog import APIMetaPosthog
+
+
+class APIMeta(BaseModel):
+    """
+    APIMeta
+    """  # noqa: E501
+
+    auth: Optional[APIMetaAuth] = None
+    pylon_app_id: Optional[StrictStr] = Field(
+        default=None,
+        description="the Pylon app ID for usepylon.com chat support",
+        alias="pylonAppId",
+    )
+    posthog: Optional[APIMetaPosthog] = None
+    allow_signup: Optional[StrictBool] = Field(
+        default=None,
+        description="whether or not users can sign up for this instance",
+        alias="allowSignup",
+    )
+    allow_invites: Optional[StrictBool] = Field(
+        default=None,
+        description="whether or not users can invite other users to this instance",
+        alias="allowInvites",
+    )
+    allow_create_tenant: Optional[StrictBool] = Field(
+        default=None,
+        description="whether or not users can create new tenants",
+        alias="allowCreateTenant",
+    )
+    allow_change_password: Optional[StrictBool] = Field(
+        default=None,
+        description="whether or not users can change their password",
+        alias="allowChangePassword",
+    )
+    __properties: ClassVar[List[str]] = [
+        "auth",
+        "pylonAppId",
+        "posthog",
+        "allowSignup",
+        "allowInvites",
+        "allowCreateTenant",
+        "allowChangePassword",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of APIMeta from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of auth
+        if self.auth:
+            _dict["auth"] = self.auth.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of posthog
+        if self.posthog:
+            _dict["posthog"] = self.posthog.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of APIMeta from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "auth": (
+                    APIMetaAuth.from_dict(obj["auth"])
+                    if obj.get("auth") is not None
+                    else None
+                ),
+                "pylonAppId": obj.get("pylonAppId"),
+                "posthog": (
+                    APIMetaPosthog.from_dict(obj["posthog"])
+                    if obj.get("posthog") is not None
+                    else None
+                ),
+                "allowSignup": obj.get("allowSignup"),
+                "allowInvites": obj.get("allowInvites"),
+                "allowCreateTenant": obj.get("allowCreateTenant"),
+                "allowChangePassword": obj.get("allowChangePassword"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_meta_auth.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_meta_auth.py
new file mode 100644
index 00000000..5ca29092
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_meta_auth.py
@@ -0,0 +1,85 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class APIMetaAuth(BaseModel):
+    """
+    APIMetaAuth
+    """  # noqa: E501
+
+    schemes: Optional[List[StrictStr]] = Field(
+        default=None, description="the supported types of authentication"
+    )
+    __properties: ClassVar[List[str]] = ["schemes"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of APIMetaAuth from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of APIMetaAuth from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"schemes": obj.get("schemes")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_meta_integration.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_meta_integration.py
new file mode 100644
index 00000000..f4f361c9
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_meta_integration.py
@@ -0,0 +1,88 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
+from typing_extensions import Self
+
+
+class APIMetaIntegration(BaseModel):
+    """
+    APIMetaIntegration
+    """  # noqa: E501
+
+    name: StrictStr = Field(description="the name of the integration")
+    enabled: StrictBool = Field(
+        description="whether this integration is enabled on the instance"
+    )
+    __properties: ClassVar[List[str]] = ["name", "enabled"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of APIMetaIntegration from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of APIMetaIntegration from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {"name": obj.get("name"), "enabled": obj.get("enabled")}
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_meta_posthog.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_meta_posthog.py
new file mode 100644
index 00000000..da6052c2
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_meta_posthog.py
@@ -0,0 +1,90 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class APIMetaPosthog(BaseModel):
+    """
+    APIMetaPosthog
+    """  # noqa: E501
+
+    api_key: Optional[StrictStr] = Field(
+        default=None, description="the PostHog API key", alias="apiKey"
+    )
+    api_host: Optional[StrictStr] = Field(
+        default=None, description="the PostHog API host", alias="apiHost"
+    )
+    __properties: ClassVar[List[str]] = ["apiKey", "apiHost"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of APIMetaPosthog from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of APIMetaPosthog from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {"apiKey": obj.get("apiKey"), "apiHost": obj.get("apiHost")}
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_resource_meta.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_resource_meta.py
new file mode 100644
index 00000000..8c353248
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_resource_meta.py
@@ -0,0 +1,98 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Annotated, Self
+
+
+class APIResourceMeta(BaseModel):
+    """
+    APIResourceMeta
+    """  # noqa: E501
+
+    id: Annotated[str, Field(min_length=0, strict=True, max_length=36)] = Field(
+        description="the id of this resource, in UUID format"
+    )
+    created_at: datetime = Field(
+        description="the time that this resource was created", alias="createdAt"
+    )
+    updated_at: datetime = Field(
+        description="the time that this resource was last updated", alias="updatedAt"
+    )
+    __properties: ClassVar[List[str]] = ["id", "createdAt", "updatedAt"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of APIResourceMeta from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of APIResourceMeta from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "id": obj.get("id"),
+                "createdAt": obj.get("createdAt"),
+                "updatedAt": obj.get("updatedAt"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_token.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_token.py
new file mode 100644
index 00000000..e469e3af
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/api_token.py
@@ -0,0 +1,105 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Annotated, Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+
+
+class APIToken(BaseModel):
+    """
+    APIToken
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    name: Annotated[str, Field(strict=True, max_length=255)] = Field(
+        description="The name of the API token."
+    )
+    expires_at: datetime = Field(
+        description="When the API token expires.", alias="expiresAt"
+    )
+    __properties: ClassVar[List[str]] = ["metadata", "name", "expiresAt"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of APIToken from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of APIToken from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "name": obj.get("name"),
+                "expiresAt": obj.get("expiresAt"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/bulk_create_event_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/bulk_create_event_request.py
new file mode 100644
index 00000000..8d08d394
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/bulk_create_event_request.py
@@ -0,0 +1,100 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.create_event_request import CreateEventRequest
+
+
+class BulkCreateEventRequest(BaseModel):
+    """
+    BulkCreateEventRequest
+    """  # noqa: E501
+
+    events: List[CreateEventRequest]
+    __properties: ClassVar[List[str]] = ["events"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of BulkCreateEventRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of each item in events (list)
+        _items = []
+        if self.events:
+            for _item_events in self.events:
+                if _item_events:
+                    _items.append(_item_events.to_dict())
+            _dict["events"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of BulkCreateEventRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "events": (
+                    [CreateEventRequest.from_dict(_item) for _item in obj["events"]]
+                    if obj.get("events") is not None
+                    else None
+                )
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/bulk_create_event_response.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/bulk_create_event_response.py
new file mode 100644
index 00000000..768c5c90
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/bulk_create_event_response.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.event import Event
+
+
+class BulkCreateEventResponse(BaseModel):
+    """
+    BulkCreateEventResponse
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    events: List[Event] = Field(description="The events.")
+    __properties: ClassVar[List[str]] = ["metadata", "events"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of BulkCreateEventResponse from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in events (list)
+        _items = []
+        if self.events:
+            for _item_events in self.events:
+                if _item_events:
+                    _items.append(_item_events.to_dict())
+            _dict["events"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of BulkCreateEventResponse from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "events": (
+                    [Event.from_dict(_item) for _item in obj["events"]]
+                    if obj.get("events") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cancel_event_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cancel_event_request.py
new file mode 100644
index 00000000..3fa171ad
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cancel_event_request.py
@@ -0,0 +1,85 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Annotated, Self
+
+
+class CancelEventRequest(BaseModel):
+    """
+    CancelEventRequest
+    """  # noqa: E501
+
+    event_ids: List[
+        Annotated[str, Field(min_length=36, strict=True, max_length=36)]
+    ] = Field(alias="eventIds")
+    __properties: ClassVar[List[str]] = ["eventIds"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of CancelEventRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of CancelEventRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"eventIds": obj.get("eventIds")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cancel_step_run_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cancel_step_run_request.py
new file mode 100644
index 00000000..69e97297
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cancel_step_run_request.py
@@ -0,0 +1,83 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel
+from typing_extensions import Self
+
+
+class CancelStepRunRequest(BaseModel):
+    """
+    CancelStepRunRequest
+    """  # noqa: E501
+
+    input: Dict[str, Any]
+    __properties: ClassVar[List[str]] = ["input"]
+
+    model_config = {
+        "populate_by_name": True,
+        "validate_assignment": True,
+        "protected_namespaces": (),
+    }
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of CancelStepRunRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of CancelStepRunRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"input": obj.get("input")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/concurrency_limit_strategy.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/concurrency_limit_strategy.py
new file mode 100644
index 00000000..74460b5e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/concurrency_limit_strategy.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class ConcurrencyLimitStrategy(str, Enum):
+    """
+    ConcurrencyLimitStrategy
+    """
+
+    """
+    allowed enum values
+    """
+    CANCEL_IN_PROGRESS = "CANCEL_IN_PROGRESS"
+    DROP_NEWEST = "DROP_NEWEST"
+    QUEUE_NEWEST = "QUEUE_NEWEST"
+    GROUP_ROUND_ROBIN = "GROUP_ROUND_ROBIN"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of ConcurrencyLimitStrategy from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_api_token_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_api_token_request.py
new file mode 100644
index 00000000..5614ef0a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_api_token_request.py
@@ -0,0 +1,92 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Annotated, Self
+
+
+class CreateAPITokenRequest(BaseModel):
+    """
+    CreateAPITokenRequest
+    """  # noqa: E501
+
+    name: Annotated[str, Field(strict=True, max_length=255)] = Field(
+        description="A name for the API token."
+    )
+    expires_in: Optional[StrictStr] = Field(
+        default=None,
+        description="The duration for which the token is valid.",
+        alias="expiresIn",
+    )
+    __properties: ClassVar[List[str]] = ["name", "expiresIn"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of CreateAPITokenRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of CreateAPITokenRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {"name": obj.get("name"), "expiresIn": obj.get("expiresIn")}
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_api_token_response.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_api_token_response.py
new file mode 100644
index 00000000..2fb1e62d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_api_token_response.py
@@ -0,0 +1,83 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class CreateAPITokenResponse(BaseModel):
+    """
+    CreateAPITokenResponse
+    """  # noqa: E501
+
+    token: StrictStr = Field(description="The API token.")
+    __properties: ClassVar[List[str]] = ["token"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of CreateAPITokenResponse from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of CreateAPITokenResponse from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"token": obj.get("token")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_cron_workflow_trigger_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_cron_workflow_trigger_request.py
new file mode 100644
index 00000000..e2b49df0
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_cron_workflow_trigger_request.py
@@ -0,0 +1,98 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class CreateCronWorkflowTriggerRequest(BaseModel):
+    """
+    CreateCronWorkflowTriggerRequest
+    """  # noqa: E501
+
+    input: Dict[str, Any]
+    additional_metadata: Dict[str, Any] = Field(alias="additionalMetadata")
+    cron_name: StrictStr = Field(alias="cronName")
+    cron_expression: StrictStr = Field(alias="cronExpression")
+    __properties: ClassVar[List[str]] = [
+        "input",
+        "additionalMetadata",
+        "cronName",
+        "cronExpression",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of CreateCronWorkflowTriggerRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of CreateCronWorkflowTriggerRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "input": obj.get("input"),
+                "additionalMetadata": obj.get("additionalMetadata"),
+                "cronName": obj.get("cronName"),
+                "cronExpression": obj.get("cronExpression"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_event_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_event_request.py
new file mode 100644
index 00000000..adc37ce6
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_event_request.py
@@ -0,0 +1,95 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class CreateEventRequest(BaseModel):
+    """
+    CreateEventRequest
+    """  # noqa: E501
+
+    key: StrictStr = Field(description="The key for the event.")
+    data: Dict[str, Any] = Field(description="The data for the event.")
+    additional_metadata: Optional[Dict[str, Any]] = Field(
+        default=None,
+        description="Additional metadata for the event.",
+        alias="additionalMetadata",
+    )
+    __properties: ClassVar[List[str]] = ["key", "data", "additionalMetadata"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of CreateEventRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of CreateEventRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "key": obj.get("key"),
+                "data": obj.get("data"),
+                "additionalMetadata": obj.get("additionalMetadata"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_pull_request_from_step_run.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_pull_request_from_step_run.py
new file mode 100644
index 00000000..0984ff06
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_pull_request_from_step_run.py
@@ -0,0 +1,83 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class CreatePullRequestFromStepRun(BaseModel):
+    """
+    CreatePullRequestFromStepRun
+    """  # noqa: E501
+
+    branch_name: StrictStr = Field(alias="branchName")
+    __properties: ClassVar[List[str]] = ["branchName"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of CreatePullRequestFromStepRun from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of CreatePullRequestFromStepRun from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"branchName": obj.get("branchName")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_sns_integration_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_sns_integration_request.py
new file mode 100644
index 00000000..ddb76cd1
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_sns_integration_request.py
@@ -0,0 +1,85 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class CreateSNSIntegrationRequest(BaseModel):
+    """
+    CreateSNSIntegrationRequest
+    """  # noqa: E501
+
+    topic_arn: StrictStr = Field(
+        description="The Amazon Resource Name (ARN) of the SNS topic.", alias="topicArn"
+    )
+    __properties: ClassVar[List[str]] = ["topicArn"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of CreateSNSIntegrationRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of CreateSNSIntegrationRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"topicArn": obj.get("topicArn")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_tenant_alert_email_group_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_tenant_alert_email_group_request.py
new file mode 100644
index 00000000..bc3a6953
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_tenant_alert_email_group_request.py
@@ -0,0 +1,83 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class CreateTenantAlertEmailGroupRequest(BaseModel):
+    """
+    CreateTenantAlertEmailGroupRequest
+    """  # noqa: E501
+
+    emails: List[StrictStr] = Field(description="A list of emails for users")
+    __properties: ClassVar[List[str]] = ["emails"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of CreateTenantAlertEmailGroupRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of CreateTenantAlertEmailGroupRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"emails": obj.get("emails")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_tenant_invite_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_tenant_invite_request.py
new file mode 100644
index 00000000..83450b48
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_tenant_invite_request.py
@@ -0,0 +1,86 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.tenant_member_role import TenantMemberRole
+
+
+class CreateTenantInviteRequest(BaseModel):
+    """
+    CreateTenantInviteRequest
+    """  # noqa: E501
+
+    email: StrictStr = Field(description="The email of the user to invite.")
+    role: TenantMemberRole = Field(description="The role of the user in the tenant.")
+    __properties: ClassVar[List[str]] = ["email", "role"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of CreateTenantInviteRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of CreateTenantInviteRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"email": obj.get("email"), "role": obj.get("role")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_tenant_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_tenant_request.py
new file mode 100644
index 00000000..84946f57
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/create_tenant_request.py
@@ -0,0 +1,84 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class CreateTenantRequest(BaseModel):
+    """
+    CreateTenantRequest
+    """  # noqa: E501
+
+    name: StrictStr = Field(description="The name of the tenant.")
+    slug: StrictStr = Field(description="The slug of the tenant.")
+    __properties: ClassVar[List[str]] = ["name", "slug"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of CreateTenantRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of CreateTenantRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"name": obj.get("name"), "slug": obj.get("slug")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cron_workflows.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cron_workflows.py
new file mode 100644
index 00000000..8005e407
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cron_workflows.py
@@ -0,0 +1,131 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.cron_workflows_method import CronWorkflowsMethod
+
+
+class CronWorkflows(BaseModel):
+    """
+    CronWorkflows
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    tenant_id: StrictStr = Field(alias="tenantId")
+    workflow_version_id: StrictStr = Field(alias="workflowVersionId")
+    workflow_id: StrictStr = Field(alias="workflowId")
+    workflow_name: StrictStr = Field(alias="workflowName")
+    cron: StrictStr
+    name: Optional[StrictStr] = None
+    input: Optional[Dict[str, Any]] = None
+    additional_metadata: Optional[Dict[str, Any]] = Field(
+        default=None, alias="additionalMetadata"
+    )
+    enabled: StrictBool
+    method: CronWorkflowsMethod
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "tenantId",
+        "workflowVersionId",
+        "workflowId",
+        "workflowName",
+        "cron",
+        "name",
+        "input",
+        "additionalMetadata",
+        "enabled",
+        "method",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of CronWorkflows from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of CronWorkflows from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "tenantId": obj.get("tenantId"),
+                "workflowVersionId": obj.get("workflowVersionId"),
+                "workflowId": obj.get("workflowId"),
+                "workflowName": obj.get("workflowName"),
+                "cron": obj.get("cron"),
+                "name": obj.get("name"),
+                "input": obj.get("input"),
+                "additionalMetadata": obj.get("additionalMetadata"),
+                "enabled": obj.get("enabled"),
+                "method": obj.get("method"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cron_workflows_list.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cron_workflows_list.py
new file mode 100644
index 00000000..b0ab6967
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cron_workflows_list.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.cron_workflows import CronWorkflows
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+
+
+class CronWorkflowsList(BaseModel):
+    """
+    CronWorkflowsList
+    """  # noqa: E501
+
+    rows: Optional[List[CronWorkflows]] = None
+    pagination: Optional[PaginationResponse] = None
+    __properties: ClassVar[List[str]] = ["rows", "pagination"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of CronWorkflowsList from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of CronWorkflowsList from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "rows": (
+                    [CronWorkflows.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cron_workflows_method.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cron_workflows_method.py
new file mode 100644
index 00000000..1f671fb5
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cron_workflows_method.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class CronWorkflowsMethod(str, Enum):
+    """
+    CronWorkflowsMethod
+    """
+
+    """
+    allowed enum values
+    """
+    DEFAULT = "DEFAULT"
+    API = "API"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of CronWorkflowsMethod from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cron_workflows_order_by_field.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cron_workflows_order_by_field.py
new file mode 100644
index 00000000..b95d199a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/cron_workflows_order_by_field.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class CronWorkflowsOrderByField(str, Enum):
+    """
+    CronWorkflowsOrderByField
+    """
+
+    """
+    allowed enum values
+    """
+    NAME = "name"
+    CREATEDAT = "createdAt"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of CronWorkflowsOrderByField from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event.py
new file mode 100644
index 00000000..4838a3ec
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event.py
@@ -0,0 +1,143 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.event_workflow_run_summary import (
+    EventWorkflowRunSummary,
+)
+from hatchet_sdk.clients.rest.models.tenant import Tenant
+
+
+class Event(BaseModel):
+    """
+    Event
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    key: StrictStr = Field(description="The key for the event.")
+    tenant: Optional[Tenant] = Field(
+        default=None, description="The tenant associated with this event."
+    )
+    tenant_id: StrictStr = Field(
+        description="The ID of the tenant associated with this event.", alias="tenantId"
+    )
+    workflow_run_summary: Optional[EventWorkflowRunSummary] = Field(
+        default=None,
+        description="The workflow run summary for this event.",
+        alias="workflowRunSummary",
+    )
+    additional_metadata: Optional[Dict[str, Any]] = Field(
+        default=None,
+        description="Additional metadata for the event.",
+        alias="additionalMetadata",
+    )
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "key",
+        "tenant",
+        "tenantId",
+        "workflowRunSummary",
+        "additionalMetadata",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of Event from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of tenant
+        if self.tenant:
+            _dict["tenant"] = self.tenant.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of workflow_run_summary
+        if self.workflow_run_summary:
+            _dict["workflowRunSummary"] = self.workflow_run_summary.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of Event from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "key": obj.get("key"),
+                "tenant": (
+                    Tenant.from_dict(obj["tenant"])
+                    if obj.get("tenant") is not None
+                    else None
+                ),
+                "tenantId": obj.get("tenantId"),
+                "workflowRunSummary": (
+                    EventWorkflowRunSummary.from_dict(obj["workflowRunSummary"])
+                    if obj.get("workflowRunSummary") is not None
+                    else None
+                ),
+                "additionalMetadata": obj.get("additionalMetadata"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_data.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_data.py
new file mode 100644
index 00000000..eb0d6128
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_data.py
@@ -0,0 +1,83 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class EventData(BaseModel):
+    """
+    EventData
+    """  # noqa: E501
+
+    data: StrictStr = Field(description="The data for the event (JSON bytes).")
+    __properties: ClassVar[List[str]] = ["data"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of EventData from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of EventData from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"data": obj.get("data")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_key_list.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_key_list.py
new file mode 100644
index 00000000..c56595ae
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_key_list.py
@@ -0,0 +1,98 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+
+
+class EventKeyList(BaseModel):
+    """
+    EventKeyList
+    """  # noqa: E501
+
+    pagination: Optional[PaginationResponse] = None
+    rows: Optional[List[StrictStr]] = None
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of EventKeyList from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of EventKeyList from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": obj.get("rows"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_list.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_list.py
new file mode 100644
index 00000000..5c928005
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_list.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.event import Event
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+
+
+class EventList(BaseModel):
+    """
+    EventList
+    """  # noqa: E501
+
+    pagination: Optional[PaginationResponse] = None
+    rows: Optional[List[Event]] = None
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of EventList from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of EventList from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": (
+                    [Event.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_order_by_direction.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_order_by_direction.py
new file mode 100644
index 00000000..24255e0d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_order_by_direction.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class EventOrderByDirection(str, Enum):
+    """
+    EventOrderByDirection
+    """
+
+    """
+    allowed enum values
+    """
+    ASC = "asc"
+    DESC = "desc"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of EventOrderByDirection from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_order_by_field.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_order_by_field.py
new file mode 100644
index 00000000..da2193c3
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_order_by_field.py
@@ -0,0 +1,36 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class EventOrderByField(str, Enum):
+    """
+    EventOrderByField
+    """
+
+    """
+    allowed enum values
+    """
+    CREATEDAT = "createdAt"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of EventOrderByField from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_update_cancel200_response.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_update_cancel200_response.py
new file mode 100644
index 00000000..6723ec30
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_update_cancel200_response.py
@@ -0,0 +1,85 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Annotated, Self
+
+
+class EventUpdateCancel200Response(BaseModel):
+    """
+    EventUpdateCancel200Response
+    """  # noqa: E501
+
+    workflow_run_ids: Optional[
+        List[Annotated[str, Field(min_length=36, strict=True, max_length=36)]]
+    ] = Field(default=None, alias="workflowRunIds")
+    __properties: ClassVar[List[str]] = ["workflowRunIds"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of EventUpdateCancel200Response from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of EventUpdateCancel200Response from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"workflowRunIds": obj.get("workflowRunIds")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_workflow_run_summary.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_workflow_run_summary.py
new file mode 100644
index 00000000..c378441b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/event_workflow_run_summary.py
@@ -0,0 +1,116 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt
+from typing_extensions import Self
+
+
+class EventWorkflowRunSummary(BaseModel):
+    """
+    EventWorkflowRunSummary
+    """  # noqa: E501
+
+    pending: Optional[StrictInt] = Field(
+        default=None, description="The number of pending runs."
+    )
+    running: Optional[StrictInt] = Field(
+        default=None, description="The number of running runs."
+    )
+    queued: Optional[StrictInt] = Field(
+        default=None, description="The number of queued runs."
+    )
+    succeeded: Optional[StrictInt] = Field(
+        default=None, description="The number of succeeded runs."
+    )
+    failed: Optional[StrictInt] = Field(
+        default=None, description="The number of failed runs."
+    )
+    cancelled: Optional[StrictInt] = Field(
+        default=None, description="The number of cancelled runs."
+    )
+    __properties: ClassVar[List[str]] = [
+        "pending",
+        "running",
+        "queued",
+        "succeeded",
+        "failed",
+        "cancelled",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of EventWorkflowRunSummary from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of EventWorkflowRunSummary from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pending": obj.get("pending"),
+                "running": obj.get("running"),
+                "queued": obj.get("queued"),
+                "succeeded": obj.get("succeeded"),
+                "failed": obj.get("failed"),
+                "cancelled": obj.get("cancelled"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/events.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/events.py
new file mode 100644
index 00000000..ec8c1cd1
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/events.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.event import Event
+
+
+class Events(BaseModel):
+    """
+    Events
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    events: List[Event] = Field(description="The events.")
+    __properties: ClassVar[List[str]] = ["metadata", "events"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of Events from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in events (list)
+        _items = []
+        if self.events:
+            for _item_events in self.events:
+                if _item_events:
+                    _items.append(_item_events.to_dict())
+            _dict["events"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of Events from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "events": (
+                    [Event.from_dict(_item) for _item in obj["events"]]
+                    if obj.get("events") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/get_step_run_diff_response.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/get_step_run_diff_response.py
new file mode 100644
index 00000000..b9dbc435
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/get_step_run_diff_response.py
@@ -0,0 +1,100 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.step_run_diff import StepRunDiff
+
+
+class GetStepRunDiffResponse(BaseModel):
+    """
+    GetStepRunDiffResponse
+    """  # noqa: E501
+
+    diffs: List[StepRunDiff]
+    __properties: ClassVar[List[str]] = ["diffs"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of GetStepRunDiffResponse from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of each item in diffs (list)
+        _items = []
+        if self.diffs:
+            for _item_diffs in self.diffs:
+                if _item_diffs:
+                    _items.append(_item_diffs.to_dict())
+            _dict["diffs"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of GetStepRunDiffResponse from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "diffs": (
+                    [StepRunDiff.from_dict(_item) for _item in obj["diffs"]]
+                    if obj.get("diffs") is not None
+                    else None
+                )
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/github_app_installation.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/github_app_installation.py
new file mode 100644
index 00000000..35bbc230
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/github_app_installation.py
@@ -0,0 +1,107 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+
+
+class GithubAppInstallation(BaseModel):
+    """
+    GithubAppInstallation
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    installation_settings_url: StrictStr
+    account_name: StrictStr
+    account_avatar_url: StrictStr
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "installation_settings_url",
+        "account_name",
+        "account_avatar_url",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of GithubAppInstallation from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of GithubAppInstallation from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "installation_settings_url": obj.get("installation_settings_url"),
+                "account_name": obj.get("account_name"),
+                "account_avatar_url": obj.get("account_avatar_url"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/github_branch.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/github_branch.py
new file mode 100644
index 00000000..16501da3
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/github_branch.py
@@ -0,0 +1,86 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, StrictBool, StrictStr
+from typing_extensions import Self
+
+
+class GithubBranch(BaseModel):
+    """
+    GithubBranch
+    """  # noqa: E501
+
+    branch_name: StrictStr
+    is_default: StrictBool
+    __properties: ClassVar[List[str]] = ["branch_name", "is_default"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of GithubBranch from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of GithubBranch from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {"branch_name": obj.get("branch_name"), "is_default": obj.get("is_default")}
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/github_repo.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/github_repo.py
new file mode 100644
index 00000000..3bc4d179
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/github_repo.py
@@ -0,0 +1,86 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, StrictStr
+from typing_extensions import Self
+
+
+class GithubRepo(BaseModel):
+    """
+    GithubRepo
+    """  # noqa: E501
+
+    repo_owner: StrictStr
+    repo_name: StrictStr
+    __properties: ClassVar[List[str]] = ["repo_owner", "repo_name"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of GithubRepo from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of GithubRepo from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {"repo_owner": obj.get("repo_owner"), "repo_name": obj.get("repo_name")}
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/info_get_version200_response.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/info_get_version200_response.py
new file mode 100644
index 00000000..93100ac4
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/info_get_version200_response.py
@@ -0,0 +1,83 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, StrictStr
+from typing_extensions import Self
+
+
+class InfoGetVersion200Response(BaseModel):
+    """
+    InfoGetVersion200Response
+    """  # noqa: E501
+
+    version: StrictStr
+    __properties: ClassVar[List[str]] = ["version"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of InfoGetVersion200Response from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of InfoGetVersion200Response from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"version": obj.get("version")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/job.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/job.py
new file mode 100644
index 00000000..c412ef68
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/job.py
@@ -0,0 +1,132 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.step import Step
+
+
+class Job(BaseModel):
+    """
+    Job
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    tenant_id: StrictStr = Field(alias="tenantId")
+    version_id: StrictStr = Field(alias="versionId")
+    name: StrictStr
+    description: Optional[StrictStr] = Field(
+        default=None, description="The description of the job."
+    )
+    steps: List[Step]
+    timeout: Optional[StrictStr] = Field(
+        default=None, description="The timeout of the job."
+    )
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "tenantId",
+        "versionId",
+        "name",
+        "description",
+        "steps",
+        "timeout",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of Job from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in steps (list)
+        _items = []
+        if self.steps:
+            for _item_steps in self.steps:
+                if _item_steps:
+                    _items.append(_item_steps.to_dict())
+            _dict["steps"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of Job from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "tenantId": obj.get("tenantId"),
+                "versionId": obj.get("versionId"),
+                "name": obj.get("name"),
+                "description": obj.get("description"),
+                "steps": (
+                    [Step.from_dict(_item) for _item in obj["steps"]]
+                    if obj.get("steps") is not None
+                    else None
+                ),
+                "timeout": obj.get("timeout"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/job_run.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/job_run.py
new file mode 100644
index 00000000..3a7ec051
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/job_run.py
@@ -0,0 +1,176 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.job import Job
+from hatchet_sdk.clients.rest.models.job_run_status import JobRunStatus
+
+
+class JobRun(BaseModel):
+    """
+    JobRun
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    tenant_id: StrictStr = Field(alias="tenantId")
+    workflow_run_id: StrictStr = Field(alias="workflowRunId")
+    workflow_run: Optional[WorkflowRun] = Field(default=None, alias="workflowRun")
+    job_id: StrictStr = Field(alias="jobId")
+    job: Optional[Job] = None
+    ticker_id: Optional[StrictStr] = Field(default=None, alias="tickerId")
+    step_runs: Optional[List[StepRun]] = Field(default=None, alias="stepRuns")
+    status: JobRunStatus
+    result: Optional[Dict[str, Any]] = None
+    started_at: Optional[datetime] = Field(default=None, alias="startedAt")
+    finished_at: Optional[datetime] = Field(default=None, alias="finishedAt")
+    timeout_at: Optional[datetime] = Field(default=None, alias="timeoutAt")
+    cancelled_at: Optional[datetime] = Field(default=None, alias="cancelledAt")
+    cancelled_reason: Optional[StrictStr] = Field(default=None, alias="cancelledReason")
+    cancelled_error: Optional[StrictStr] = Field(default=None, alias="cancelledError")
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "tenantId",
+        "workflowRunId",
+        "workflowRun",
+        "jobId",
+        "job",
+        "tickerId",
+        "stepRuns",
+        "status",
+        "result",
+        "startedAt",
+        "finishedAt",
+        "timeoutAt",
+        "cancelledAt",
+        "cancelledReason",
+        "cancelledError",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of JobRun from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of workflow_run
+        if self.workflow_run:
+            _dict["workflowRun"] = self.workflow_run.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of job
+        if self.job:
+            _dict["job"] = self.job.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in step_runs (list)
+        _items = []
+        if self.step_runs:
+            for _item_step_runs in self.step_runs:
+                if _item_step_runs:
+                    _items.append(_item_step_runs.to_dict())
+            _dict["stepRuns"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of JobRun from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "tenantId": obj.get("tenantId"),
+                "workflowRunId": obj.get("workflowRunId"),
+                "workflowRun": (
+                    WorkflowRun.from_dict(obj["workflowRun"])
+                    if obj.get("workflowRun") is not None
+                    else None
+                ),
+                "jobId": obj.get("jobId"),
+                "job": (
+                    Job.from_dict(obj["job"]) if obj.get("job") is not None else None
+                ),
+                "tickerId": obj.get("tickerId"),
+                "stepRuns": (
+                    [StepRun.from_dict(_item) for _item in obj["stepRuns"]]
+                    if obj.get("stepRuns") is not None
+                    else None
+                ),
+                "status": obj.get("status"),
+                "result": obj.get("result"),
+                "startedAt": obj.get("startedAt"),
+                "finishedAt": obj.get("finishedAt"),
+                "timeoutAt": obj.get("timeoutAt"),
+                "cancelledAt": obj.get("cancelledAt"),
+                "cancelledReason": obj.get("cancelledReason"),
+                "cancelledError": obj.get("cancelledError"),
+            }
+        )
+        return _obj
+
+
+from hatchet_sdk.clients.rest.models.step_run import StepRun
+from hatchet_sdk.clients.rest.models.workflow_run import WorkflowRun
+
+# TODO: Rewrite to not use raise_errors
+JobRun.model_rebuild(raise_errors=False)
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/job_run_status.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/job_run_status.py
new file mode 100644
index 00000000..68a14711
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/job_run_status.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class JobRunStatus(str, Enum):
+    """
+    JobRunStatus
+    """
+
+    """
+    allowed enum values
+    """
+    PENDING = "PENDING"
+    RUNNING = "RUNNING"
+    SUCCEEDED = "SUCCEEDED"
+    FAILED = "FAILED"
+    CANCELLED = "CANCELLED"
+    BACKOFF = "BACKOFF"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of JobRunStatus from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/link_github_repository_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/link_github_repository_request.py
new file mode 100644
index 00000000..e5ddf6e5
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/link_github_repository_request.py
@@ -0,0 +1,106 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Annotated, Self
+
+
+class LinkGithubRepositoryRequest(BaseModel):
+    """
+    LinkGithubRepositoryRequest
+    """  # noqa: E501
+
+    installation_id: Annotated[
+        str, Field(min_length=36, strict=True, max_length=36)
+    ] = Field(description="The repository name.", alias="installationId")
+    git_repo_name: StrictStr = Field(
+        description="The repository name.", alias="gitRepoName"
+    )
+    git_repo_owner: StrictStr = Field(
+        description="The repository owner.", alias="gitRepoOwner"
+    )
+    git_repo_branch: StrictStr = Field(
+        description="The repository branch.", alias="gitRepoBranch"
+    )
+    __properties: ClassVar[List[str]] = [
+        "installationId",
+        "gitRepoName",
+        "gitRepoOwner",
+        "gitRepoBranch",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of LinkGithubRepositoryRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of LinkGithubRepositoryRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "installationId": obj.get("installationId"),
+                "gitRepoName": obj.get("gitRepoName"),
+                "gitRepoOwner": obj.get("gitRepoOwner"),
+                "gitRepoBranch": obj.get("gitRepoBranch"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_api_tokens_response.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_api_tokens_response.py
new file mode 100644
index 00000000..b3590ab3
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_api_tokens_response.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_token import APIToken
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+
+
+class ListAPITokensResponse(BaseModel):
+    """
+    ListAPITokensResponse
+    """  # noqa: E501
+
+    pagination: Optional[PaginationResponse] = None
+    rows: Optional[List[APIToken]] = None
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of ListAPITokensResponse from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of ListAPITokensResponse from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": (
+                    [APIToken.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_github_app_installations_response.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_github_app_installations_response.py
new file mode 100644
index 00000000..401fc266
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_github_app_installations_response.py
@@ -0,0 +1,112 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.github_app_installation import (
+    GithubAppInstallation,
+)
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+
+
+class ListGithubAppInstallationsResponse(BaseModel):
+    """
+    ListGithubAppInstallationsResponse
+    """  # noqa: E501
+
+    pagination: PaginationResponse
+    rows: List[GithubAppInstallation]
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of ListGithubAppInstallationsResponse from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item in self.rows:
+                if _item:
+                    _items.append(_item.to_dict())
+            _dict["rows"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of ListGithubAppInstallationsResponse from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": (
+                    [GithubAppInstallation.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_pull_requests_response.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_pull_requests_response.py
new file mode 100644
index 00000000..589d4c45
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_pull_requests_response.py
@@ -0,0 +1,100 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pull_request import PullRequest
+
+
+class ListPullRequestsResponse(BaseModel):
+    """
+    ListPullRequestsResponse
+    """  # noqa: E501
+
+    pull_requests: List[PullRequest] = Field(alias="pullRequests")
+    __properties: ClassVar[List[str]] = ["pullRequests"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of ListPullRequestsResponse from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of each item in pull_requests (list)
+        _items = []
+        if self.pull_requests:
+            for _item_pull_requests in self.pull_requests:
+                if _item_pull_requests:
+                    _items.append(_item_pull_requests.to_dict())
+            _dict["pullRequests"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of ListPullRequestsResponse from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pullRequests": (
+                    [PullRequest.from_dict(_item) for _item in obj["pullRequests"]]
+                    if obj.get("pullRequests") is not None
+                    else None
+                )
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_slack_webhooks.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_slack_webhooks.py
new file mode 100644
index 00000000..e86956d3
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_slack_webhooks.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.slack_webhook import SlackWebhook
+
+
+class ListSlackWebhooks(BaseModel):
+    """
+    ListSlackWebhooks
+    """  # noqa: E501
+
+    pagination: PaginationResponse
+    rows: List[SlackWebhook]
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of ListSlackWebhooks from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of ListSlackWebhooks from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": (
+                    [SlackWebhook.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_sns_integrations.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_sns_integrations.py
new file mode 100644
index 00000000..130e9127
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/list_sns_integrations.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.sns_integration import SNSIntegration
+
+
+class ListSNSIntegrations(BaseModel):
+    """
+    ListSNSIntegrations
+    """  # noqa: E501
+
+    pagination: PaginationResponse
+    rows: List[SNSIntegration]
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of ListSNSIntegrations from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of ListSNSIntegrations from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": (
+                    [SNSIntegration.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line.py
new file mode 100644
index 00000000..ee4299cf
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line.py
@@ -0,0 +1,94 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class LogLine(BaseModel):
+    """
+    LogLine
+    """  # noqa: E501
+
+    created_at: datetime = Field(
+        description="The creation date of the log line.", alias="createdAt"
+    )
+    message: StrictStr = Field(description="The log message.")
+    metadata: Dict[str, Any] = Field(description="The log metadata.")
+    __properties: ClassVar[List[str]] = ["createdAt", "message", "metadata"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of LogLine from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of LogLine from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "createdAt": obj.get("createdAt"),
+                "message": obj.get("message"),
+                "metadata": obj.get("metadata"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line_level.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line_level.py
new file mode 100644
index 00000000..63fbec41
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line_level.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class LogLineLevel(str, Enum):
+    """
+    LogLineLevel
+    """
+
+    """
+    allowed enum values
+    """
+    DEBUG = "DEBUG"
+    INFO = "INFO"
+    WARN = "WARN"
+    ERROR = "ERROR"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of LogLineLevel from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line_list.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line_list.py
new file mode 100644
index 00000000..e05d186a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line_list.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.log_line import LogLine
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+
+
+class LogLineList(BaseModel):
+    """
+    LogLineList
+    """  # noqa: E501
+
+    pagination: Optional[PaginationResponse] = None
+    rows: Optional[List[LogLine]] = None
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of LogLineList from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of LogLineList from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": (
+                    [LogLine.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line_order_by_direction.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line_order_by_direction.py
new file mode 100644
index 00000000..5f66f59b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line_order_by_direction.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class LogLineOrderByDirection(str, Enum):
+    """
+    LogLineOrderByDirection
+    """
+
+    """
+    allowed enum values
+    """
+    ASC = "asc"
+    DESC = "desc"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of LogLineOrderByDirection from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line_order_by_field.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line_order_by_field.py
new file mode 100644
index 00000000..93b92526
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/log_line_order_by_field.py
@@ -0,0 +1,36 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class LogLineOrderByField(str, Enum):
+    """
+    LogLineOrderByField
+    """
+
+    """
+    allowed enum values
+    """
+    CREATEDAT = "createdAt"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of LogLineOrderByField from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/pagination_response.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/pagination_response.py
new file mode 100644
index 00000000..2994dee9
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/pagination_response.py
@@ -0,0 +1,95 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt
+from typing_extensions import Self
+
+
+class PaginationResponse(BaseModel):
+    """
+    PaginationResponse
+    """  # noqa: E501
+
+    current_page: Optional[StrictInt] = Field(
+        default=None, description="the current page"
+    )
+    next_page: Optional[StrictInt] = Field(default=None, description="the next page")
+    num_pages: Optional[StrictInt] = Field(
+        default=None, description="the total number of pages for listing"
+    )
+    __properties: ClassVar[List[str]] = ["current_page", "next_page", "num_pages"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of PaginationResponse from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of PaginationResponse from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "current_page": obj.get("current_page"),
+                "next_page": obj.get("next_page"),
+                "num_pages": obj.get("num_pages"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/pull_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/pull_request.py
new file mode 100644
index 00000000..c1462591
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/pull_request.py
@@ -0,0 +1,112 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pull_request_state import PullRequestState
+
+
+class PullRequest(BaseModel):
+    """
+    PullRequest
+    """  # noqa: E501
+
+    repository_owner: StrictStr = Field(alias="repositoryOwner")
+    repository_name: StrictStr = Field(alias="repositoryName")
+    pull_request_id: StrictInt = Field(alias="pullRequestID")
+    pull_request_title: StrictStr = Field(alias="pullRequestTitle")
+    pull_request_number: StrictInt = Field(alias="pullRequestNumber")
+    pull_request_head_branch: StrictStr = Field(alias="pullRequestHeadBranch")
+    pull_request_base_branch: StrictStr = Field(alias="pullRequestBaseBranch")
+    pull_request_state: PullRequestState = Field(alias="pullRequestState")
+    __properties: ClassVar[List[str]] = [
+        "repositoryOwner",
+        "repositoryName",
+        "pullRequestID",
+        "pullRequestTitle",
+        "pullRequestNumber",
+        "pullRequestHeadBranch",
+        "pullRequestBaseBranch",
+        "pullRequestState",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of PullRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of PullRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "repositoryOwner": obj.get("repositoryOwner"),
+                "repositoryName": obj.get("repositoryName"),
+                "pullRequestID": obj.get("pullRequestID"),
+                "pullRequestTitle": obj.get("pullRequestTitle"),
+                "pullRequestNumber": obj.get("pullRequestNumber"),
+                "pullRequestHeadBranch": obj.get("pullRequestHeadBranch"),
+                "pullRequestBaseBranch": obj.get("pullRequestBaseBranch"),
+                "pullRequestState": obj.get("pullRequestState"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/pull_request_state.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/pull_request_state.py
new file mode 100644
index 00000000..a44d06cc
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/pull_request_state.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class PullRequestState(str, Enum):
+    """
+    PullRequestState
+    """
+
+    """
+    allowed enum values
+    """
+    OPEN = "open"
+    CLOSED = "closed"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of PullRequestState from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/queue_metrics.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/queue_metrics.py
new file mode 100644
index 00000000..d19066dd
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/queue_metrics.py
@@ -0,0 +1,97 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt
+from typing_extensions import Self
+
+
+class QueueMetrics(BaseModel):
+    """
+    QueueMetrics
+    """  # noqa: E501
+
+    num_queued: StrictInt = Field(
+        description="The number of items in the queue.", alias="numQueued"
+    )
+    num_running: StrictInt = Field(
+        description="The number of items running.", alias="numRunning"
+    )
+    num_pending: StrictInt = Field(
+        description="The number of items pending.", alias="numPending"
+    )
+    __properties: ClassVar[List[str]] = ["numQueued", "numRunning", "numPending"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of QueueMetrics from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of QueueMetrics from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "numQueued": obj.get("numQueued"),
+                "numRunning": obj.get("numRunning"),
+                "numPending": obj.get("numPending"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rate_limit.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rate_limit.py
new file mode 100644
index 00000000..0bf88522
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rate_limit.py
@@ -0,0 +1,117 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
+from typing_extensions import Self
+
+
+class RateLimit(BaseModel):
+    """
+    RateLimit
+    """  # noqa: E501
+
+    key: StrictStr = Field(description="The key for the rate limit.")
+    tenant_id: StrictStr = Field(
+        description="The ID of the tenant associated with this rate limit.",
+        alias="tenantId",
+    )
+    limit_value: StrictInt = Field(
+        description="The maximum number of requests allowed within the window.",
+        alias="limitValue",
+    )
+    value: StrictInt = Field(
+        description="The current number of requests made within the window."
+    )
+    window: StrictStr = Field(
+        description="The window of time in which the limitValue is enforced."
+    )
+    last_refill: datetime = Field(
+        description="The last time the rate limit was refilled.", alias="lastRefill"
+    )
+    __properties: ClassVar[List[str]] = [
+        "key",
+        "tenantId",
+        "limitValue",
+        "value",
+        "window",
+        "lastRefill",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of RateLimit from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of RateLimit from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "key": obj.get("key"),
+                "tenantId": obj.get("tenantId"),
+                "limitValue": obj.get("limitValue"),
+                "value": obj.get("value"),
+                "window": obj.get("window"),
+                "lastRefill": obj.get("lastRefill"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rate_limit_list.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rate_limit_list.py
new file mode 100644
index 00000000..e9f2847d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rate_limit_list.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.rate_limit import RateLimit
+
+
+class RateLimitList(BaseModel):
+    """
+    RateLimitList
+    """  # noqa: E501
+
+    pagination: Optional[PaginationResponse] = None
+    rows: Optional[List[RateLimit]] = None
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of RateLimitList from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of RateLimitList from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": (
+                    [RateLimit.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rate_limit_order_by_direction.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rate_limit_order_by_direction.py
new file mode 100644
index 00000000..64451da9
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rate_limit_order_by_direction.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class RateLimitOrderByDirection(str, Enum):
+    """
+    RateLimitOrderByDirection
+    """
+
+    """
+    allowed enum values
+    """
+    ASC = "asc"
+    DESC = "desc"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of RateLimitOrderByDirection from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rate_limit_order_by_field.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rate_limit_order_by_field.py
new file mode 100644
index 00000000..6b5077be
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rate_limit_order_by_field.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class RateLimitOrderByField(str, Enum):
+    """
+    RateLimitOrderByField
+    """
+
+    """
+    allowed enum values
+    """
+    KEY = "key"
+    VALUE = "value"
+    LIMITVALUE = "limitValue"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of RateLimitOrderByField from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/recent_step_runs.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/recent_step_runs.py
new file mode 100644
index 00000000..9b8a8249
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/recent_step_runs.py
@@ -0,0 +1,118 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.step_run_status import StepRunStatus
+
+
+class RecentStepRuns(BaseModel):
+    """
+    RecentStepRuns
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    action_id: StrictStr = Field(description="The action id.", alias="actionId")
+    status: StepRunStatus
+    started_at: Optional[datetime] = Field(default=None, alias="startedAt")
+    finished_at: Optional[datetime] = Field(default=None, alias="finishedAt")
+    cancelled_at: Optional[datetime] = Field(default=None, alias="cancelledAt")
+    workflow_run_id: StrictStr = Field(alias="workflowRunId")
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "actionId",
+        "status",
+        "startedAt",
+        "finishedAt",
+        "cancelledAt",
+        "workflowRunId",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of RecentStepRuns from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of RecentStepRuns from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "actionId": obj.get("actionId"),
+                "status": obj.get("status"),
+                "startedAt": obj.get("startedAt"),
+                "finishedAt": obj.get("finishedAt"),
+                "cancelledAt": obj.get("cancelledAt"),
+                "workflowRunId": obj.get("workflowRunId"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/reject_invite_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/reject_invite_request.py
new file mode 100644
index 00000000..13399345
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/reject_invite_request.py
@@ -0,0 +1,83 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Annotated, Self
+
+
+class RejectInviteRequest(BaseModel):
+    """
+    RejectInviteRequest
+    """  # noqa: E501
+
+    invite: Annotated[str, Field(min_length=36, strict=True, max_length=36)]
+    __properties: ClassVar[List[str]] = ["invite"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of RejectInviteRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of RejectInviteRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"invite": obj.get("invite")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/replay_event_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/replay_event_request.py
new file mode 100644
index 00000000..0a5ef723
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/replay_event_request.py
@@ -0,0 +1,85 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Annotated, Self
+
+
+class ReplayEventRequest(BaseModel):
+    """
+    ReplayEventRequest
+    """  # noqa: E501
+
+    event_ids: List[
+        Annotated[str, Field(min_length=36, strict=True, max_length=36)]
+    ] = Field(alias="eventIds")
+    __properties: ClassVar[List[str]] = ["eventIds"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of ReplayEventRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of ReplayEventRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"eventIds": obj.get("eventIds")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/replay_workflow_runs_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/replay_workflow_runs_request.py
new file mode 100644
index 00000000..de5b2797
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/replay_workflow_runs_request.py
@@ -0,0 +1,85 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Annotated, Self
+
+
+class ReplayWorkflowRunsRequest(BaseModel):
+    """
+    ReplayWorkflowRunsRequest
+    """  # noqa: E501
+
+    workflow_run_ids: List[
+        Annotated[str, Field(min_length=36, strict=True, max_length=36)]
+    ] = Field(alias="workflowRunIds")
+    __properties: ClassVar[List[str]] = ["workflowRunIds"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of ReplayWorkflowRunsRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of ReplayWorkflowRunsRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"workflowRunIds": obj.get("workflowRunIds")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/replay_workflow_runs_response.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/replay_workflow_runs_response.py
new file mode 100644
index 00000000..d8a9609d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/replay_workflow_runs_response.py
@@ -0,0 +1,100 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.workflow_run import WorkflowRun
+
+
+class ReplayWorkflowRunsResponse(BaseModel):
+    """
+    ReplayWorkflowRunsResponse
+    """  # noqa: E501
+
+    workflow_runs: List[WorkflowRun] = Field(alias="workflowRuns")
+    __properties: ClassVar[List[str]] = ["workflowRuns"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of ReplayWorkflowRunsResponse from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of each item in workflow_runs (list)
+        _items = []
+        if self.workflow_runs:
+            for _item_workflow_runs in self.workflow_runs:
+                if _item_workflow_runs:
+                    _items.append(_item_workflow_runs.to_dict())
+            _dict["workflowRuns"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of ReplayWorkflowRunsResponse from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "workflowRuns": (
+                    [WorkflowRun.from_dict(_item) for _item in obj["workflowRuns"]]
+                    if obj.get("workflowRuns") is not None
+                    else None
+                )
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rerun_step_run_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rerun_step_run_request.py
new file mode 100644
index 00000000..f8b28066
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/rerun_step_run_request.py
@@ -0,0 +1,83 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+
+class RerunStepRunRequest(BaseModel):
+    """
+    RerunStepRunRequest
+    """  # noqa: E501
+
+    input: Dict[str, Any]
+    __properties: ClassVar[List[str]] = ["input"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of RerunStepRunRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of RerunStepRunRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"input": obj.get("input")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/schedule_workflow_run_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/schedule_workflow_run_request.py
new file mode 100644
index 00000000..c5b4753f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/schedule_workflow_run_request.py
@@ -0,0 +1,92 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Self
+
+
+class ScheduleWorkflowRunRequest(BaseModel):
+    """
+    ScheduleWorkflowRunRequest
+    """  # noqa: E501
+
+    input: Dict[str, Any]
+    additional_metadata: Dict[str, Any] = Field(alias="additionalMetadata")
+    trigger_at: datetime = Field(alias="triggerAt")
+    __properties: ClassVar[List[str]] = ["input", "additionalMetadata", "triggerAt"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of ScheduleWorkflowRunRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of ScheduleWorkflowRunRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "input": obj.get("input"),
+                "additionalMetadata": obj.get("additionalMetadata"),
+                "triggerAt": obj.get("triggerAt"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_run_status.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_run_status.py
new file mode 100644
index 00000000..f0f2a17f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_run_status.py
@@ -0,0 +1,42 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class ScheduledRunStatus(str, Enum):
+    """
+    ScheduledRunStatus
+    """
+
+    """
+    allowed enum values
+    """
+    PENDING = "PENDING"
+    RUNNING = "RUNNING"
+    SUCCEEDED = "SUCCEEDED"
+    FAILED = "FAILED"
+    CANCELLED = "CANCELLED"
+    QUEUED = "QUEUED"
+    SCHEDULED = "SCHEDULED"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of ScheduledRunStatus from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_workflows.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_workflows.py
new file mode 100644
index 00000000..95bf7169
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_workflows.py
@@ -0,0 +1,149 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Annotated, Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.scheduled_workflows_method import (
+    ScheduledWorkflowsMethod,
+)
+from hatchet_sdk.clients.rest.models.workflow_run_status import WorkflowRunStatus
+
+
+class ScheduledWorkflows(BaseModel):
+    """
+    ScheduledWorkflows
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    tenant_id: StrictStr = Field(alias="tenantId")
+    workflow_version_id: StrictStr = Field(alias="workflowVersionId")
+    workflow_id: StrictStr = Field(alias="workflowId")
+    workflow_name: StrictStr = Field(alias="workflowName")
+    trigger_at: datetime = Field(alias="triggerAt")
+    input: Optional[Dict[str, Any]] = None
+    additional_metadata: Optional[Dict[str, Any]] = Field(
+        default=None, alias="additionalMetadata"
+    )
+    workflow_run_created_at: Optional[datetime] = Field(
+        default=None, alias="workflowRunCreatedAt"
+    )
+    workflow_run_name: Optional[StrictStr] = Field(
+        default=None, alias="workflowRunName"
+    )
+    workflow_run_status: Optional[WorkflowRunStatus] = Field(
+        default=None, alias="workflowRunStatus"
+    )
+    workflow_run_id: Optional[
+        Annotated[str, Field(min_length=36, strict=True, max_length=36)]
+    ] = Field(default=None, alias="workflowRunId")
+    method: ScheduledWorkflowsMethod
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "tenantId",
+        "workflowVersionId",
+        "workflowId",
+        "workflowName",
+        "triggerAt",
+        "input",
+        "additionalMetadata",
+        "workflowRunCreatedAt",
+        "workflowRunName",
+        "workflowRunStatus",
+        "workflowRunId",
+        "method",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of ScheduledWorkflows from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of ScheduledWorkflows from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "tenantId": obj.get("tenantId"),
+                "workflowVersionId": obj.get("workflowVersionId"),
+                "workflowId": obj.get("workflowId"),
+                "workflowName": obj.get("workflowName"),
+                "triggerAt": obj.get("triggerAt"),
+                "input": obj.get("input"),
+                "additionalMetadata": obj.get("additionalMetadata"),
+                "workflowRunCreatedAt": obj.get("workflowRunCreatedAt"),
+                "workflowRunName": obj.get("workflowRunName"),
+                "workflowRunStatus": obj.get("workflowRunStatus"),
+                "workflowRunId": obj.get("workflowRunId"),
+                "method": obj.get("method"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_workflows_list.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_workflows_list.py
new file mode 100644
index 00000000..67468b5e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_workflows_list.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.scheduled_workflows import ScheduledWorkflows
+
+
+class ScheduledWorkflowsList(BaseModel):
+    """
+    ScheduledWorkflowsList
+    """  # noqa: E501
+
+    rows: Optional[List[ScheduledWorkflows]] = None
+    pagination: Optional[PaginationResponse] = None
+    __properties: ClassVar[List[str]] = ["rows", "pagination"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of ScheduledWorkflowsList from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of ScheduledWorkflowsList from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "rows": (
+                    [ScheduledWorkflows.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_workflows_method.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_workflows_method.py
new file mode 100644
index 00000000..f7016461
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_workflows_method.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class ScheduledWorkflowsMethod(str, Enum):
+    """
+    ScheduledWorkflowsMethod
+    """
+
+    """
+    allowed enum values
+    """
+    DEFAULT = "DEFAULT"
+    API = "API"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of ScheduledWorkflowsMethod from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_workflows_order_by_field.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_workflows_order_by_field.py
new file mode 100644
index 00000000..0372abd3
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/scheduled_workflows_order_by_field.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class ScheduledWorkflowsOrderByField(str, Enum):
+    """
+    ScheduledWorkflowsOrderByField
+    """
+
+    """
+    allowed enum values
+    """
+    TRIGGERAT = "triggerAt"
+    CREATEDAT = "createdAt"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of ScheduledWorkflowsOrderByField from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/semaphore_slots.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/semaphore_slots.py
new file mode 100644
index 00000000..1e7c6242
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/semaphore_slots.py
@@ -0,0 +1,113 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.step_run_status import StepRunStatus
+
+
+class SemaphoreSlots(BaseModel):
+    """
+    SemaphoreSlots
+    """  # noqa: E501
+
+    step_run_id: StrictStr = Field(description="The step run id.", alias="stepRunId")
+    action_id: StrictStr = Field(description="The action id.", alias="actionId")
+    started_at: Optional[datetime] = Field(
+        default=None, description="The time this slot was started.", alias="startedAt"
+    )
+    timeout_at: Optional[datetime] = Field(
+        default=None, description="The time this slot will timeout.", alias="timeoutAt"
+    )
+    workflow_run_id: StrictStr = Field(
+        description="The workflow run id.", alias="workflowRunId"
+    )
+    status: StepRunStatus
+    __properties: ClassVar[List[str]] = [
+        "stepRunId",
+        "actionId",
+        "startedAt",
+        "timeoutAt",
+        "workflowRunId",
+        "status",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of SemaphoreSlots from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of SemaphoreSlots from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "stepRunId": obj.get("stepRunId"),
+                "actionId": obj.get("actionId"),
+                "startedAt": obj.get("startedAt"),
+                "timeoutAt": obj.get("timeoutAt"),
+                "workflowRunId": obj.get("workflowRunId"),
+                "status": obj.get("status"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/slack_webhook.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/slack_webhook.py
new file mode 100644
index 00000000..6cc3f4c8
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/slack_webhook.py
@@ -0,0 +1,127 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+
+
+class SlackWebhook(BaseModel):
+    """
+    SlackWebhook
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    tenant_id: StrictStr = Field(
+        description="The unique identifier for the tenant that the SNS integration belongs to.",
+        alias="tenantId",
+    )
+    team_name: StrictStr = Field(
+        description="The team name associated with this slack webhook.",
+        alias="teamName",
+    )
+    team_id: StrictStr = Field(
+        description="The team id associated with this slack webhook.", alias="teamId"
+    )
+    channel_name: StrictStr = Field(
+        description="The channel name associated with this slack webhook.",
+        alias="channelName",
+    )
+    channel_id: StrictStr = Field(
+        description="The channel id associated with this slack webhook.",
+        alias="channelId",
+    )
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "tenantId",
+        "teamName",
+        "teamId",
+        "channelName",
+        "channelId",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of SlackWebhook from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of SlackWebhook from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "tenantId": obj.get("tenantId"),
+                "teamName": obj.get("teamName"),
+                "teamId": obj.get("teamId"),
+                "channelName": obj.get("channelName"),
+                "channelId": obj.get("channelId"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/sns_integration.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/sns_integration.py
new file mode 100644
index 00000000..7fcda4aa
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/sns_integration.py
@@ -0,0 +1,114 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+
+
+class SNSIntegration(BaseModel):
+    """
+    SNSIntegration
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    tenant_id: StrictStr = Field(
+        description="The unique identifier for the tenant that the SNS integration belongs to.",
+        alias="tenantId",
+    )
+    topic_arn: StrictStr = Field(
+        description="The Amazon Resource Name (ARN) of the SNS topic.", alias="topicArn"
+    )
+    ingest_url: Optional[StrictStr] = Field(
+        default=None, description="The URL to send SNS messages to.", alias="ingestUrl"
+    )
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "tenantId",
+        "topicArn",
+        "ingestUrl",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of SNSIntegration from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of SNSIntegration from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "tenantId": obj.get("tenantId"),
+                "topicArn": obj.get("topicArn"),
+                "ingestUrl": obj.get("ingestUrl"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step.py
new file mode 100644
index 00000000..2014b7e9
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step.py
@@ -0,0 +1,123 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+
+
+class Step(BaseModel):
+    """
+    Step
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    readable_id: StrictStr = Field(
+        description="The readable id of the step.", alias="readableId"
+    )
+    tenant_id: StrictStr = Field(alias="tenantId")
+    job_id: StrictStr = Field(alias="jobId")
+    action: StrictStr
+    timeout: Optional[StrictStr] = Field(
+        default=None, description="The timeout of the step."
+    )
+    children: Optional[List[StrictStr]] = None
+    parents: Optional[List[StrictStr]] = None
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "readableId",
+        "tenantId",
+        "jobId",
+        "action",
+        "timeout",
+        "children",
+        "parents",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of Step from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of Step from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "readableId": obj.get("readableId"),
+                "tenantId": obj.get("tenantId"),
+                "jobId": obj.get("jobId"),
+                "action": obj.get("action"),
+                "timeout": obj.get("timeout"),
+                "children": obj.get("children"),
+                "parents": obj.get("parents"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run.py
new file mode 100644
index 00000000..7e6b4b22
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run.py
@@ -0,0 +1,202 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.step import Step
+from hatchet_sdk.clients.rest.models.step_run_status import StepRunStatus
+
+
+class StepRun(BaseModel):
+    """
+    StepRun
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    tenant_id: StrictStr = Field(alias="tenantId")
+    job_run_id: StrictStr = Field(alias="jobRunId")
+    job_run: Optional[JobRun] = Field(default=None, alias="jobRun")
+    step_id: StrictStr = Field(alias="stepId")
+    step: Optional[Step] = None
+    child_workflows_count: Optional[StrictInt] = Field(
+        default=None, alias="childWorkflowsCount"
+    )
+    parents: Optional[List[StrictStr]] = None
+    child_workflow_runs: Optional[List[StrictStr]] = Field(
+        default=None, alias="childWorkflowRuns"
+    )
+    worker_id: Optional[StrictStr] = Field(default=None, alias="workerId")
+    input: Optional[StrictStr] = None
+    output: Optional[StrictStr] = None
+    status: StepRunStatus
+    requeue_after: Optional[datetime] = Field(default=None, alias="requeueAfter")
+    result: Optional[Dict[str, Any]] = None
+    error: Optional[StrictStr] = None
+    started_at: Optional[datetime] = Field(default=None, alias="startedAt")
+    started_at_epoch: Optional[StrictInt] = Field(default=None, alias="startedAtEpoch")
+    finished_at: Optional[datetime] = Field(default=None, alias="finishedAt")
+    finished_at_epoch: Optional[StrictInt] = Field(
+        default=None, alias="finishedAtEpoch"
+    )
+    timeout_at: Optional[datetime] = Field(default=None, alias="timeoutAt")
+    timeout_at_epoch: Optional[StrictInt] = Field(default=None, alias="timeoutAtEpoch")
+    cancelled_at: Optional[datetime] = Field(default=None, alias="cancelledAt")
+    cancelled_at_epoch: Optional[StrictInt] = Field(
+        default=None, alias="cancelledAtEpoch"
+    )
+    cancelled_reason: Optional[StrictStr] = Field(default=None, alias="cancelledReason")
+    cancelled_error: Optional[StrictStr] = Field(default=None, alias="cancelledError")
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "tenantId",
+        "jobRunId",
+        "jobRun",
+        "stepId",
+        "step",
+        "childWorkflowsCount",
+        "parents",
+        "childWorkflowRuns",
+        "workerId",
+        "input",
+        "output",
+        "status",
+        "requeueAfter",
+        "result",
+        "error",
+        "startedAt",
+        "startedAtEpoch",
+        "finishedAt",
+        "finishedAtEpoch",
+        "timeoutAt",
+        "timeoutAtEpoch",
+        "cancelledAt",
+        "cancelledAtEpoch",
+        "cancelledReason",
+        "cancelledError",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of StepRun from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of job_run
+        if self.job_run:
+            _dict["jobRun"] = self.job_run.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of step
+        if self.step:
+            _dict["step"] = self.step.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of StepRun from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "tenantId": obj.get("tenantId"),
+                "jobRunId": obj.get("jobRunId"),
+                "jobRun": (
+                    JobRun.from_dict(obj["jobRun"])
+                    if obj.get("jobRun") is not None
+                    else None
+                ),
+                "stepId": obj.get("stepId"),
+                "step": (
+                    Step.from_dict(obj["step"]) if obj.get("step") is not None else None
+                ),
+                "childWorkflowsCount": obj.get("childWorkflowsCount"),
+                "parents": obj.get("parents"),
+                "childWorkflowRuns": obj.get("childWorkflowRuns"),
+                "workerId": obj.get("workerId"),
+                "input": obj.get("input"),
+                "output": obj.get("output"),
+                "status": obj.get("status"),
+                "requeueAfter": obj.get("requeueAfter"),
+                "result": obj.get("result"),
+                "error": obj.get("error"),
+                "startedAt": obj.get("startedAt"),
+                "startedAtEpoch": obj.get("startedAtEpoch"),
+                "finishedAt": obj.get("finishedAt"),
+                "finishedAtEpoch": obj.get("finishedAtEpoch"),
+                "timeoutAt": obj.get("timeoutAt"),
+                "timeoutAtEpoch": obj.get("timeoutAtEpoch"),
+                "cancelledAt": obj.get("cancelledAt"),
+                "cancelledAtEpoch": obj.get("cancelledAtEpoch"),
+                "cancelledReason": obj.get("cancelledReason"),
+                "cancelledError": obj.get("cancelledError"),
+            }
+        )
+        return _obj
+
+
+from hatchet_sdk.clients.rest.models.job_run import JobRun
+
+# TODO: Rewrite to not use raise_errors
+StepRun.model_rebuild(raise_errors=False)
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_archive.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_archive.py
new file mode 100644
index 00000000..7476174d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_archive.py
@@ -0,0 +1,142 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
+from typing_extensions import Self
+
+
+class StepRunArchive(BaseModel):
+    """
+    StepRunArchive
+    """  # noqa: E501
+
+    step_run_id: StrictStr = Field(alias="stepRunId")
+    order: StrictInt
+    input: Optional[StrictStr] = None
+    output: Optional[StrictStr] = None
+    started_at: Optional[datetime] = Field(default=None, alias="startedAt")
+    error: Optional[StrictStr] = None
+    retry_count: StrictInt = Field(alias="retryCount")
+    created_at: datetime = Field(alias="createdAt")
+    started_at_epoch: Optional[StrictInt] = Field(default=None, alias="startedAtEpoch")
+    finished_at: Optional[datetime] = Field(default=None, alias="finishedAt")
+    finished_at_epoch: Optional[StrictInt] = Field(
+        default=None, alias="finishedAtEpoch"
+    )
+    timeout_at: Optional[datetime] = Field(default=None, alias="timeoutAt")
+    timeout_at_epoch: Optional[StrictInt] = Field(default=None, alias="timeoutAtEpoch")
+    cancelled_at: Optional[datetime] = Field(default=None, alias="cancelledAt")
+    cancelled_at_epoch: Optional[StrictInt] = Field(
+        default=None, alias="cancelledAtEpoch"
+    )
+    cancelled_reason: Optional[StrictStr] = Field(default=None, alias="cancelledReason")
+    cancelled_error: Optional[StrictStr] = Field(default=None, alias="cancelledError")
+    __properties: ClassVar[List[str]] = [
+        "stepRunId",
+        "order",
+        "input",
+        "output",
+        "startedAt",
+        "error",
+        "retryCount",
+        "createdAt",
+        "startedAtEpoch",
+        "finishedAt",
+        "finishedAtEpoch",
+        "timeoutAt",
+        "timeoutAtEpoch",
+        "cancelledAt",
+        "cancelledAtEpoch",
+        "cancelledReason",
+        "cancelledError",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of StepRunArchive from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of StepRunArchive from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "stepRunId": obj.get("stepRunId"),
+                "order": obj.get("order"),
+                "input": obj.get("input"),
+                "output": obj.get("output"),
+                "startedAt": obj.get("startedAt"),
+                "error": obj.get("error"),
+                "retryCount": obj.get("retryCount"),
+                "createdAt": obj.get("createdAt"),
+                "startedAtEpoch": obj.get("startedAtEpoch"),
+                "finishedAt": obj.get("finishedAt"),
+                "finishedAtEpoch": obj.get("finishedAtEpoch"),
+                "timeoutAt": obj.get("timeoutAt"),
+                "timeoutAtEpoch": obj.get("timeoutAtEpoch"),
+                "cancelledAt": obj.get("cancelledAt"),
+                "cancelledAtEpoch": obj.get("cancelledAtEpoch"),
+                "cancelledReason": obj.get("cancelledReason"),
+                "cancelledError": obj.get("cancelledError"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_archive_list.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_archive_list.py
new file mode 100644
index 00000000..eb4bcef2
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_archive_list.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.step_run_archive import StepRunArchive
+
+
+class StepRunArchiveList(BaseModel):
+    """
+    StepRunArchiveList
+    """  # noqa: E501
+
+    pagination: Optional[PaginationResponse] = None
+    rows: Optional[List[StepRunArchive]] = None
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of StepRunArchiveList from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of StepRunArchiveList from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": (
+                    [StepRunArchive.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_diff.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_diff.py
new file mode 100644
index 00000000..78848dd7
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_diff.py
@@ -0,0 +1,91 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, StrictStr
+from typing_extensions import Self
+
+
+class StepRunDiff(BaseModel):
+    """
+    StepRunDiff
+    """  # noqa: E501
+
+    key: StrictStr
+    original: StrictStr
+    modified: StrictStr
+    __properties: ClassVar[List[str]] = ["key", "original", "modified"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of StepRunDiff from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of StepRunDiff from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "key": obj.get("key"),
+                "original": obj.get("original"),
+                "modified": obj.get("modified"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_event.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_event.py
new file mode 100644
index 00000000..c5909d24
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_event.py
@@ -0,0 +1,120 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.step_run_event_reason import StepRunEventReason
+from hatchet_sdk.clients.rest.models.step_run_event_severity import StepRunEventSeverity
+
+
+class StepRunEvent(BaseModel):
+    """
+    StepRunEvent
+    """  # noqa: E501
+
+    id: StrictInt
+    time_first_seen: datetime = Field(alias="timeFirstSeen")
+    time_last_seen: datetime = Field(alias="timeLastSeen")
+    step_run_id: Optional[StrictStr] = Field(default=None, alias="stepRunId")
+    workflow_run_id: Optional[StrictStr] = Field(default=None, alias="workflowRunId")
+    reason: StepRunEventReason
+    severity: StepRunEventSeverity
+    message: StrictStr
+    count: StrictInt
+    data: Optional[Dict[str, Any]] = None
+    __properties: ClassVar[List[str]] = [
+        "id",
+        "timeFirstSeen",
+        "timeLastSeen",
+        "stepRunId",
+        "workflowRunId",
+        "reason",
+        "severity",
+        "message",
+        "count",
+        "data",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of StepRunEvent from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of StepRunEvent from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "id": obj.get("id"),
+                "timeFirstSeen": obj.get("timeFirstSeen"),
+                "timeLastSeen": obj.get("timeLastSeen"),
+                "stepRunId": obj.get("stepRunId"),
+                "workflowRunId": obj.get("workflowRunId"),
+                "reason": obj.get("reason"),
+                "severity": obj.get("severity"),
+                "message": obj.get("message"),
+                "count": obj.get("count"),
+                "data": obj.get("data"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_event_list.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_event_list.py
new file mode 100644
index 00000000..f146eb8e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_event_list.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.step_run_event import StepRunEvent
+
+
+class StepRunEventList(BaseModel):
+    """
+    StepRunEventList
+    """  # noqa: E501
+
+    pagination: Optional[PaginationResponse] = None
+    rows: Optional[List[StepRunEvent]] = None
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of StepRunEventList from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of StepRunEventList from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": (
+                    [StepRunEvent.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_event_reason.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_event_reason.py
new file mode 100644
index 00000000..487fde06
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_event_reason.py
@@ -0,0 +1,52 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class StepRunEventReason(str, Enum):
+    """
+    StepRunEventReason
+    """
+
+    """
+    allowed enum values
+    """
+    REQUEUED_NO_WORKER = "REQUEUED_NO_WORKER"
+    REQUEUED_RATE_LIMIT = "REQUEUED_RATE_LIMIT"
+    SCHEDULING_TIMED_OUT = "SCHEDULING_TIMED_OUT"
+    ASSIGNED = "ASSIGNED"
+    STARTED = "STARTED"
+    ACKNOWLEDGED = "ACKNOWLEDGED"
+    FINISHED = "FINISHED"
+    FAILED = "FAILED"
+    RETRYING = "RETRYING"
+    CANCELLED = "CANCELLED"
+    TIMEOUT_REFRESHED = "TIMEOUT_REFRESHED"
+    REASSIGNED = "REASSIGNED"
+    TIMED_OUT = "TIMED_OUT"
+    SLOT_RELEASED = "SLOT_RELEASED"
+    RETRIED_BY_USER = "RETRIED_BY_USER"
+    WORKFLOW_RUN_GROUP_KEY_SUCCEEDED = "WORKFLOW_RUN_GROUP_KEY_SUCCEEDED"
+    WORKFLOW_RUN_GROUP_KEY_FAILED = "WORKFLOW_RUN_GROUP_KEY_FAILED"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of StepRunEventReason from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_event_severity.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_event_severity.py
new file mode 100644
index 00000000..a8a39912
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_event_severity.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class StepRunEventSeverity(str, Enum):
+    """
+    StepRunEventSeverity
+    """
+
+    """
+    allowed enum values
+    """
+    INFO = "INFO"
+    WARNING = "WARNING"
+    CRITICAL = "CRITICAL"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of StepRunEventSeverity from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_status.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_status.py
new file mode 100644
index 00000000..1e1114f0
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/step_run_status.py
@@ -0,0 +1,44 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class StepRunStatus(str, Enum):
+    """
+    StepRunStatus
+    """
+
+    """
+    allowed enum values
+    """
+    PENDING = "PENDING"
+    PENDING_ASSIGNMENT = "PENDING_ASSIGNMENT"
+    ASSIGNED = "ASSIGNED"
+    RUNNING = "RUNNING"
+    SUCCEEDED = "SUCCEEDED"
+    FAILED = "FAILED"
+    CANCELLED = "CANCELLED"
+    CANCELLING = "CANCELLING"
+    BACKOFF = "BACKOFF"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of StepRunStatus from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant.py
new file mode 100644
index 00000000..97a5863e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant.py
@@ -0,0 +1,118 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+
+
+class Tenant(BaseModel):
+    """
+    Tenant
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    name: StrictStr = Field(description="The name of the tenant.")
+    slug: StrictStr = Field(description="The slug of the tenant.")
+    analytics_opt_out: Optional[StrictBool] = Field(
+        default=None,
+        description="Whether the tenant has opted out of analytics.",
+        alias="analyticsOptOut",
+    )
+    alert_member_emails: Optional[StrictBool] = Field(
+        default=None,
+        description="Whether to alert tenant members.",
+        alias="alertMemberEmails",
+    )
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "name",
+        "slug",
+        "analyticsOptOut",
+        "alertMemberEmails",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of Tenant from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of Tenant from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "name": obj.get("name"),
+                "slug": obj.get("slug"),
+                "analyticsOptOut": obj.get("analyticsOptOut"),
+                "alertMemberEmails": obj.get("alertMemberEmails"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_alert_email_group.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_alert_email_group.py
new file mode 100644
index 00000000..2b0586ed
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_alert_email_group.py
@@ -0,0 +1,98 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+
+
+class TenantAlertEmailGroup(BaseModel):
+    """
+    TenantAlertEmailGroup
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    emails: List[StrictStr] = Field(description="A list of emails for users")
+    __properties: ClassVar[List[str]] = ["metadata", "emails"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of TenantAlertEmailGroup from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of TenantAlertEmailGroup from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "emails": obj.get("emails"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_alert_email_group_list.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_alert_email_group_list.py
new file mode 100644
index 00000000..73d67df4
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_alert_email_group_list.py
@@ -0,0 +1,112 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.tenant_alert_email_group import (
+    TenantAlertEmailGroup,
+)
+
+
+class TenantAlertEmailGroupList(BaseModel):
+    """
+    TenantAlertEmailGroupList
+    """  # noqa: E501
+
+    pagination: Optional[PaginationResponse] = None
+    rows: Optional[List[TenantAlertEmailGroup]] = None
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of TenantAlertEmailGroupList from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of TenantAlertEmailGroupList from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": (
+                    [TenantAlertEmailGroup.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_alerting_settings.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_alerting_settings.py
new file mode 100644
index 00000000..e2502486
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_alerting_settings.py
@@ -0,0 +1,143 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+
+
+class TenantAlertingSettings(BaseModel):
+    """
+    TenantAlertingSettings
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    alert_member_emails: Optional[StrictBool] = Field(
+        default=None,
+        description="Whether to alert tenant members.",
+        alias="alertMemberEmails",
+    )
+    enable_workflow_run_failure_alerts: Optional[StrictBool] = Field(
+        default=None,
+        description="Whether to send alerts when workflow runs fail.",
+        alias="enableWorkflowRunFailureAlerts",
+    )
+    enable_expiring_token_alerts: Optional[StrictBool] = Field(
+        default=None,
+        description="Whether to enable alerts when tokens are approaching expiration.",
+        alias="enableExpiringTokenAlerts",
+    )
+    enable_tenant_resource_limit_alerts: Optional[StrictBool] = Field(
+        default=None,
+        description="Whether to enable alerts when tenant resources are approaching limits.",
+        alias="enableTenantResourceLimitAlerts",
+    )
+    max_alerting_frequency: StrictStr = Field(
+        description="The max frequency at which to alert.", alias="maxAlertingFrequency"
+    )
+    last_alerted_at: Optional[datetime] = Field(
+        default=None,
+        description="The last time an alert was sent.",
+        alias="lastAlertedAt",
+    )
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "alertMemberEmails",
+        "enableWorkflowRunFailureAlerts",
+        "enableExpiringTokenAlerts",
+        "enableTenantResourceLimitAlerts",
+        "maxAlertingFrequency",
+        "lastAlertedAt",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of TenantAlertingSettings from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of TenantAlertingSettings from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "alertMemberEmails": obj.get("alertMemberEmails"),
+                "enableWorkflowRunFailureAlerts": obj.get(
+                    "enableWorkflowRunFailureAlerts"
+                ),
+                "enableExpiringTokenAlerts": obj.get("enableExpiringTokenAlerts"),
+                "enableTenantResourceLimitAlerts": obj.get(
+                    "enableTenantResourceLimitAlerts"
+                ),
+                "maxAlertingFrequency": obj.get("maxAlertingFrequency"),
+                "lastAlertedAt": obj.get("lastAlertedAt"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_invite.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_invite.py
new file mode 100644
index 00000000..168bfa3c
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_invite.py
@@ -0,0 +1,120 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.tenant_member_role import TenantMemberRole
+
+
+class TenantInvite(BaseModel):
+    """
+    TenantInvite
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    email: StrictStr = Field(description="The email of the user to invite.")
+    role: TenantMemberRole = Field(description="The role of the user in the tenant.")
+    tenant_id: StrictStr = Field(
+        description="The tenant id associated with this tenant invite.",
+        alias="tenantId",
+    )
+    tenant_name: Optional[StrictStr] = Field(
+        default=None, description="The tenant name for the tenant.", alias="tenantName"
+    )
+    expires: datetime = Field(description="The time that this invite expires.")
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "email",
+        "role",
+        "tenantId",
+        "tenantName",
+        "expires",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of TenantInvite from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of TenantInvite from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "email": obj.get("email"),
+                "role": obj.get("role"),
+                "tenantId": obj.get("tenantId"),
+                "tenantName": obj.get("tenantName"),
+                "expires": obj.get("expires"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_invite_list.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_invite_list.py
new file mode 100644
index 00000000..0ed078ef
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_invite_list.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.tenant_invite import TenantInvite
+
+
+class TenantInviteList(BaseModel):
+    """
+    TenantInviteList
+    """  # noqa: E501
+
+    pagination: Optional[PaginationResponse] = None
+    rows: Optional[List[TenantInvite]] = None
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of TenantInviteList from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of TenantInviteList from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": (
+                    [TenantInvite.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_list.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_list.py
new file mode 100644
index 00000000..2dbb320e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_list.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.tenant import Tenant
+
+
+class TenantList(BaseModel):
+    """
+    TenantList
+    """  # noqa: E501
+
+    pagination: Optional[PaginationResponse] = None
+    rows: Optional[List[Tenant]] = None
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of TenantList from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of TenantList from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": (
+                    [Tenant.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_member.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_member.py
new file mode 100644
index 00000000..540230c0
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_member.py
@@ -0,0 +1,123 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.tenant import Tenant
+from hatchet_sdk.clients.rest.models.tenant_member_role import TenantMemberRole
+from hatchet_sdk.clients.rest.models.user_tenant_public import UserTenantPublic
+
+
+class TenantMember(BaseModel):
+    """
+    TenantMember
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    user: UserTenantPublic = Field(
+        description="The user associated with this tenant member."
+    )
+    role: TenantMemberRole = Field(description="The role of the user in the tenant.")
+    tenant: Optional[Tenant] = Field(
+        default=None, description="The tenant associated with this tenant member."
+    )
+    __properties: ClassVar[List[str]] = ["metadata", "user", "role", "tenant"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of TenantMember from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of user
+        if self.user:
+            _dict["user"] = self.user.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of tenant
+        if self.tenant:
+            _dict["tenant"] = self.tenant.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of TenantMember from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "user": (
+                    UserTenantPublic.from_dict(obj["user"])
+                    if obj.get("user") is not None
+                    else None
+                ),
+                "role": obj.get("role"),
+                "tenant": (
+                    Tenant.from_dict(obj["tenant"])
+                    if obj.get("tenant") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_member_list.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_member_list.py
new file mode 100644
index 00000000..5aabdcd1
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_member_list.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.tenant_member import TenantMember
+
+
+class TenantMemberList(BaseModel):
+    """
+    TenantMemberList
+    """  # noqa: E501
+
+    pagination: Optional[PaginationResponse] = None
+    rows: Optional[List[TenantMember]] = None
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of TenantMemberList from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of TenantMemberList from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": (
+                    [TenantMember.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_member_role.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_member_role.py
new file mode 100644
index 00000000..446c7044
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_member_role.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class TenantMemberRole(str, Enum):
+    """
+    TenantMemberRole
+    """
+
+    """
+    allowed enum values
+    """
+    OWNER = "OWNER"
+    ADMIN = "ADMIN"
+    MEMBER = "MEMBER"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of TenantMemberRole from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_queue_metrics.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_queue_metrics.py
new file mode 100644
index 00000000..4043d47f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_queue_metrics.py
@@ -0,0 +1,116 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.queue_metrics import QueueMetrics
+
+
+class TenantQueueMetrics(BaseModel):
+    """
+    TenantQueueMetrics
+    """  # noqa: E501
+
+    total: Optional[QueueMetrics] = Field(
+        default=None, description="The total queue metrics."
+    )
+    workflow: Optional[Dict[str, QueueMetrics]] = None
+    queues: Optional[Dict[str, StrictInt]] = None
+    __properties: ClassVar[List[str]] = ["total", "workflow", "queues"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of TenantQueueMetrics from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of total
+        if self.total:
+            _dict["total"] = self.total.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each value in workflow (dict)
+        _field_dict = {}
+        if self.workflow:
+            for _key_workflow in self.workflow:
+                if self.workflow[_key_workflow]:
+                    _field_dict[_key_workflow] = self.workflow[_key_workflow].to_dict()
+            _dict["workflow"] = _field_dict
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of TenantQueueMetrics from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "total": (
+                    QueueMetrics.from_dict(obj["total"])
+                    if obj.get("total") is not None
+                    else None
+                ),
+                "workflow": (
+                    dict(
+                        (_k, QueueMetrics.from_dict(_v))
+                        for _k, _v in obj["workflow"].items()
+                    )
+                    if obj.get("workflow") is not None
+                    else None
+                ),
+                "queues": obj.get("queues"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_resource.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_resource.py
new file mode 100644
index 00000000..0dbdbf60
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_resource.py
@@ -0,0 +1,40 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class TenantResource(str, Enum):
+    """
+    TenantResource
+    """
+
+    """
+    allowed enum values
+    """
+    WORKER = "WORKER"
+    EVENT = "EVENT"
+    WORKFLOW_RUN = "WORKFLOW_RUN"
+    CRON = "CRON"
+    SCHEDULE = "SCHEDULE"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of TenantResource from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_resource_limit.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_resource_limit.py
new file mode 100644
index 00000000..722b7854
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_resource_limit.py
@@ -0,0 +1,135 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.tenant_resource import TenantResource
+
+
+class TenantResourceLimit(BaseModel):
+    """
+    TenantResourceLimit
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    resource: TenantResource = Field(
+        description="The resource associated with this limit."
+    )
+    limit_value: StrictInt = Field(
+        description="The limit associated with this limit.", alias="limitValue"
+    )
+    alarm_value: Optional[StrictInt] = Field(
+        default=None,
+        description="The alarm value associated with this limit to warn of approaching limit value.",
+        alias="alarmValue",
+    )
+    value: StrictInt = Field(
+        description="The current value associated with this limit."
+    )
+    window: Optional[StrictStr] = Field(
+        default=None,
+        description="The meter window for the limit. (i.e. 1 day, 1 week, 1 month)",
+    )
+    last_refill: Optional[datetime] = Field(
+        default=None,
+        description="The last time the limit was refilled.",
+        alias="lastRefill",
+    )
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "resource",
+        "limitValue",
+        "alarmValue",
+        "value",
+        "window",
+        "lastRefill",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of TenantResourceLimit from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of TenantResourceLimit from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "resource": obj.get("resource"),
+                "limitValue": obj.get("limitValue"),
+                "alarmValue": obj.get("alarmValue"),
+                "value": obj.get("value"),
+                "window": obj.get("window"),
+                "lastRefill": obj.get("lastRefill"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_resource_policy.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_resource_policy.py
new file mode 100644
index 00000000..b9e5181f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_resource_policy.py
@@ -0,0 +1,102 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.tenant_resource_limit import TenantResourceLimit
+
+
+class TenantResourcePolicy(BaseModel):
+    """
+    TenantResourcePolicy
+    """  # noqa: E501
+
+    limits: List[TenantResourceLimit] = Field(
+        description="A list of resource limits for the tenant."
+    )
+    __properties: ClassVar[List[str]] = ["limits"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of TenantResourcePolicy from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of each item in limits (list)
+        _items = []
+        if self.limits:
+            for _item_limits in self.limits:
+                if _item_limits:
+                    _items.append(_item_limits.to_dict())
+            _dict["limits"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of TenantResourcePolicy from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "limits": (
+                    [TenantResourceLimit.from_dict(_item) for _item in obj["limits"]]
+                    if obj.get("limits") is not None
+                    else None
+                )
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_step_run_queue_metrics.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_step_run_queue_metrics.py
new file mode 100644
index 00000000..4b9bfc81
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/tenant_step_run_queue_metrics.py
@@ -0,0 +1,83 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, StrictInt
+from typing_extensions import Self
+
+
+class TenantStepRunQueueMetrics(BaseModel):
+    """
+    TenantStepRunQueueMetrics
+    """  # noqa: E501
+
+    queues: Optional[Dict[str, StrictInt]] = None
+    __properties: ClassVar[List[str]] = ["queues"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of TenantStepRunQueueMetrics from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of TenantStepRunQueueMetrics from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"queues": obj.get("queues")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/trigger_workflow_run_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/trigger_workflow_run_request.py
new file mode 100644
index 00000000..5600c6a0
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/trigger_workflow_run_request.py
@@ -0,0 +1,91 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Self
+
+
+class TriggerWorkflowRunRequest(BaseModel):
+    """
+    TriggerWorkflowRunRequest
+    """  # noqa: E501
+
+    input: Dict[str, Any]
+    additional_metadata: Optional[Dict[str, Any]] = Field(
+        default=None, alias="additionalMetadata"
+    )
+    __properties: ClassVar[List[str]] = ["input", "additionalMetadata"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of TriggerWorkflowRunRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of TriggerWorkflowRunRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "input": obj.get("input"),
+                "additionalMetadata": obj.get("additionalMetadata"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/update_tenant_alert_email_group_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/update_tenant_alert_email_group_request.py
new file mode 100644
index 00000000..d4dec094
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/update_tenant_alert_email_group_request.py
@@ -0,0 +1,83 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class UpdateTenantAlertEmailGroupRequest(BaseModel):
+    """
+    UpdateTenantAlertEmailGroupRequest
+    """  # noqa: E501
+
+    emails: List[StrictStr] = Field(description="A list of emails for users")
+    __properties: ClassVar[List[str]] = ["emails"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of UpdateTenantAlertEmailGroupRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of UpdateTenantAlertEmailGroupRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"emails": obj.get("emails")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/update_tenant_invite_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/update_tenant_invite_request.py
new file mode 100644
index 00000000..86c36a9b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/update_tenant_invite_request.py
@@ -0,0 +1,85 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.tenant_member_role import TenantMemberRole
+
+
+class UpdateTenantInviteRequest(BaseModel):
+    """
+    UpdateTenantInviteRequest
+    """  # noqa: E501
+
+    role: TenantMemberRole = Field(description="The role of the user in the tenant.")
+    __properties: ClassVar[List[str]] = ["role"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of UpdateTenantInviteRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of UpdateTenantInviteRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"role": obj.get("role")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/update_tenant_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/update_tenant_request.py
new file mode 100644
index 00000000..431efe00
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/update_tenant_request.py
@@ -0,0 +1,137 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
+from typing_extensions import Self
+
+
+class UpdateTenantRequest(BaseModel):
+    """
+    UpdateTenantRequest
+    """  # noqa: E501
+
+    name: Optional[StrictStr] = Field(
+        default=None, description="The name of the tenant."
+    )
+    analytics_opt_out: Optional[StrictBool] = Field(
+        default=None,
+        description="Whether the tenant has opted out of analytics.",
+        alias="analyticsOptOut",
+    )
+    alert_member_emails: Optional[StrictBool] = Field(
+        default=None,
+        description="Whether to alert tenant members.",
+        alias="alertMemberEmails",
+    )
+    enable_workflow_run_failure_alerts: Optional[StrictBool] = Field(
+        default=None,
+        description="Whether to send alerts when workflow runs fail.",
+        alias="enableWorkflowRunFailureAlerts",
+    )
+    enable_expiring_token_alerts: Optional[StrictBool] = Field(
+        default=None,
+        description="Whether to enable alerts when tokens are approaching expiration.",
+        alias="enableExpiringTokenAlerts",
+    )
+    enable_tenant_resource_limit_alerts: Optional[StrictBool] = Field(
+        default=None,
+        description="Whether to enable alerts when tenant resources are approaching limits.",
+        alias="enableTenantResourceLimitAlerts",
+    )
+    max_alerting_frequency: Optional[StrictStr] = Field(
+        default=None,
+        description="The max frequency at which to alert.",
+        alias="maxAlertingFrequency",
+    )
+    __properties: ClassVar[List[str]] = [
+        "name",
+        "analyticsOptOut",
+        "alertMemberEmails",
+        "enableWorkflowRunFailureAlerts",
+        "enableExpiringTokenAlerts",
+        "enableTenantResourceLimitAlerts",
+        "maxAlertingFrequency",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of UpdateTenantRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of UpdateTenantRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "name": obj.get("name"),
+                "analyticsOptOut": obj.get("analyticsOptOut"),
+                "alertMemberEmails": obj.get("alertMemberEmails"),
+                "enableWorkflowRunFailureAlerts": obj.get(
+                    "enableWorkflowRunFailureAlerts"
+                ),
+                "enableExpiringTokenAlerts": obj.get("enableExpiringTokenAlerts"),
+                "enableTenantResourceLimitAlerts": obj.get(
+                    "enableTenantResourceLimitAlerts"
+                ),
+                "maxAlertingFrequency": obj.get("maxAlertingFrequency"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/update_worker_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/update_worker_request.py
new file mode 100644
index 00000000..73904979
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/update_worker_request.py
@@ -0,0 +1,87 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictBool
+from typing_extensions import Self
+
+
+class UpdateWorkerRequest(BaseModel):
+    """
+    UpdateWorkerRequest
+    """  # noqa: E501
+
+    is_paused: Optional[StrictBool] = Field(
+        default=None,
+        description="Whether the worker is paused and cannot accept new runs.",
+        alias="isPaused",
+    )
+    __properties: ClassVar[List[str]] = ["isPaused"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of UpdateWorkerRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of UpdateWorkerRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"isPaused": obj.get("isPaused")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user.py
new file mode 100644
index 00000000..a806062a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user.py
@@ -0,0 +1,126 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+
+
+class User(BaseModel):
+    """
+    User
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    name: Optional[StrictStr] = Field(
+        default=None, description="The display name of the user."
+    )
+    email: StrictStr = Field(description="The email address of the user.")
+    email_verified: StrictBool = Field(
+        description="Whether the user has verified their email address.",
+        alias="emailVerified",
+    )
+    has_password: Optional[StrictBool] = Field(
+        default=None,
+        description="Whether the user has a password set.",
+        alias="hasPassword",
+    )
+    email_hash: Optional[StrictStr] = Field(
+        default=None,
+        description="A hash of the user's email address for use with Pylon Support Chat",
+        alias="emailHash",
+    )
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "name",
+        "email",
+        "emailVerified",
+        "hasPassword",
+        "emailHash",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of User from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of User from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "name": obj.get("name"),
+                "email": obj.get("email"),
+                "emailVerified": obj.get("emailVerified"),
+                "hasPassword": obj.get("hasPassword"),
+                "emailHash": obj.get("emailHash"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_change_password_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_change_password_request.py
new file mode 100644
index 00000000..b0b87ac4
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_change_password_request.py
@@ -0,0 +1,88 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class UserChangePasswordRequest(BaseModel):
+    """
+    UserChangePasswordRequest
+    """  # noqa: E501
+
+    password: StrictStr = Field(description="The password of the user.")
+    new_password: StrictStr = Field(
+        description="The new password for the user.", alias="newPassword"
+    )
+    __properties: ClassVar[List[str]] = ["password", "newPassword"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of UserChangePasswordRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of UserChangePasswordRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {"password": obj.get("password"), "newPassword": obj.get("newPassword")}
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_login_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_login_request.py
new file mode 100644
index 00000000..a9ab5a8d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_login_request.py
@@ -0,0 +1,86 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class UserLoginRequest(BaseModel):
+    """
+    UserLoginRequest
+    """  # noqa: E501
+
+    email: StrictStr = Field(description="The email address of the user.")
+    password: StrictStr = Field(description="The password of the user.")
+    __properties: ClassVar[List[str]] = ["email", "password"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of UserLoginRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of UserLoginRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {"email": obj.get("email"), "password": obj.get("password")}
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_register_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_register_request.py
new file mode 100644
index 00000000..bf0c1dfa
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_register_request.py
@@ -0,0 +1,91 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class UserRegisterRequest(BaseModel):
+    """
+    UserRegisterRequest
+    """  # noqa: E501
+
+    name: StrictStr = Field(description="The name of the user.")
+    email: StrictStr = Field(description="The email address of the user.")
+    password: StrictStr = Field(description="The password of the user.")
+    __properties: ClassVar[List[str]] = ["name", "email", "password"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of UserRegisterRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of UserRegisterRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "name": obj.get("name"),
+                "email": obj.get("email"),
+                "password": obj.get("password"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_tenant_memberships_list.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_tenant_memberships_list.py
new file mode 100644
index 00000000..98b8041b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_tenant_memberships_list.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.tenant_member import TenantMember
+
+
+class UserTenantMembershipsList(BaseModel):
+    """
+    UserTenantMembershipsList
+    """  # noqa: E501
+
+    pagination: Optional[PaginationResponse] = None
+    rows: Optional[List[TenantMember]] = None
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of UserTenantMembershipsList from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of UserTenantMembershipsList from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": (
+                    [TenantMember.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_tenant_public.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_tenant_public.py
new file mode 100644
index 00000000..42e4fe0c
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/user_tenant_public.py
@@ -0,0 +1,86 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class UserTenantPublic(BaseModel):
+    """
+    UserTenantPublic
+    """  # noqa: E501
+
+    email: StrictStr = Field(description="The email address of the user.")
+    name: Optional[StrictStr] = Field(
+        default=None, description="The display name of the user."
+    )
+    __properties: ClassVar[List[str]] = ["email", "name"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of UserTenantPublic from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of UserTenantPublic from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"email": obj.get("email"), "name": obj.get("name")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker.py
new file mode 100644
index 00000000..28b5731d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker.py
@@ -0,0 +1,100 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+
+
+class WebhookWorker(BaseModel):
+    """
+    WebhookWorker
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    name: StrictStr = Field(description="The name of the webhook worker.")
+    url: StrictStr = Field(description="The webhook url.")
+    __properties: ClassVar[List[str]] = ["metadata", "name", "url"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WebhookWorker from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WebhookWorker from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "name": obj.get("name"),
+                "url": obj.get("url"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_create_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_create_request.py
new file mode 100644
index 00000000..616277e1
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_create_request.py
@@ -0,0 +1,94 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Annotated, Self
+
+
+class WebhookWorkerCreateRequest(BaseModel):
+    """
+    WebhookWorkerCreateRequest
+    """  # noqa: E501
+
+    name: StrictStr = Field(description="The name of the webhook worker.")
+    url: StrictStr = Field(description="The webhook url.")
+    secret: Optional[Annotated[str, Field(min_length=32, strict=True)]] = Field(
+        default=None,
+        description="The secret key for validation. If not provided, a random secret will be generated.",
+    )
+    __properties: ClassVar[List[str]] = ["name", "url", "secret"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WebhookWorkerCreateRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WebhookWorkerCreateRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "name": obj.get("name"),
+                "url": obj.get("url"),
+                "secret": obj.get("secret"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_create_response.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_create_response.py
new file mode 100644
index 00000000..819edec0
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_create_response.py
@@ -0,0 +1,96 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.webhook_worker_created import WebhookWorkerCreated
+
+
+class WebhookWorkerCreateResponse(BaseModel):
+    """
+    WebhookWorkerCreateResponse
+    """  # noqa: E501
+
+    worker: Optional[WebhookWorkerCreated] = None
+    __properties: ClassVar[List[str]] = ["worker"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WebhookWorkerCreateResponse from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of worker
+        if self.worker:
+            _dict["worker"] = self.worker.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WebhookWorkerCreateResponse from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "worker": (
+                    WebhookWorkerCreated.from_dict(obj["worker"])
+                    if obj.get("worker") is not None
+                    else None
+                )
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_created.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_created.py
new file mode 100644
index 00000000..26a409ee
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_created.py
@@ -0,0 +1,102 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+
+
+class WebhookWorkerCreated(BaseModel):
+    """
+    WebhookWorkerCreated
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    name: StrictStr = Field(description="The name of the webhook worker.")
+    url: StrictStr = Field(description="The webhook url.")
+    secret: StrictStr = Field(description="The secret key for validation.")
+    __properties: ClassVar[List[str]] = ["metadata", "name", "url", "secret"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WebhookWorkerCreated from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WebhookWorkerCreated from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "name": obj.get("name"),
+                "url": obj.get("url"),
+                "secret": obj.get("secret"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_list_response.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_list_response.py
new file mode 100644
index 00000000..a221e182
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_list_response.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.webhook_worker import WebhookWorker
+
+
+class WebhookWorkerListResponse(BaseModel):
+    """
+    WebhookWorkerListResponse
+    """  # noqa: E501
+
+    pagination: Optional[PaginationResponse] = None
+    rows: Optional[List[WebhookWorker]] = None
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WebhookWorkerListResponse from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WebhookWorkerListResponse from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": (
+                    [WebhookWorker.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_request.py
new file mode 100644
index 00000000..07adaa3d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_request.py
@@ -0,0 +1,102 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.webhook_worker_request_method import (
+    WebhookWorkerRequestMethod,
+)
+
+
+class WebhookWorkerRequest(BaseModel):
+    """
+    WebhookWorkerRequest
+    """  # noqa: E501
+
+    created_at: datetime = Field(
+        description="The date and time the request was created."
+    )
+    method: WebhookWorkerRequestMethod = Field(
+        description="The HTTP method used for the request."
+    )
+    status_code: StrictInt = Field(
+        description="The HTTP status code of the response.", alias="statusCode"
+    )
+    __properties: ClassVar[List[str]] = ["created_at", "method", "statusCode"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WebhookWorkerRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WebhookWorkerRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "created_at": obj.get("created_at"),
+                "method": obj.get("method"),
+                "statusCode": obj.get("statusCode"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_request_list_response.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_request_list_response.py
new file mode 100644
index 00000000..ec813a38
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_request_list_response.py
@@ -0,0 +1,102 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.webhook_worker_request import WebhookWorkerRequest
+
+
+class WebhookWorkerRequestListResponse(BaseModel):
+    """
+    WebhookWorkerRequestListResponse
+    """  # noqa: E501
+
+    requests: Optional[List[WebhookWorkerRequest]] = Field(
+        default=None, description="The list of webhook requests."
+    )
+    __properties: ClassVar[List[str]] = ["requests"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WebhookWorkerRequestListResponse from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of each item in requests (list)
+        _items = []
+        if self.requests:
+            for _item_requests in self.requests:
+                if _item_requests:
+                    _items.append(_item_requests.to_dict())
+            _dict["requests"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WebhookWorkerRequestListResponse from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "requests": (
+                    [WebhookWorkerRequest.from_dict(_item) for _item in obj["requests"]]
+                    if obj.get("requests") is not None
+                    else None
+                )
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_request_method.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_request_method.py
new file mode 100644
index 00000000..14cb059f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/webhook_worker_request_method.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class WebhookWorkerRequestMethod(str, Enum):
+    """
+    WebhookWorkerRequestMethod
+    """
+
+    """
+    allowed enum values
+    """
+    GET = "GET"
+    POST = "POST"
+    PUT = "PUT"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of WebhookWorkerRequestMethod from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker.py
new file mode 100644
index 00000000..03e9e4c4
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker.py
@@ -0,0 +1,239 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, field_validator
+from typing_extensions import Annotated, Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.recent_step_runs import RecentStepRuns
+from hatchet_sdk.clients.rest.models.semaphore_slots import SemaphoreSlots
+from hatchet_sdk.clients.rest.models.worker_label import WorkerLabel
+from hatchet_sdk.clients.rest.models.worker_runtime_info import WorkerRuntimeInfo
+from hatchet_sdk.clients.rest.models.worker_type import WorkerType
+
+
+class Worker(BaseModel):
+    """
+    Worker
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    name: StrictStr = Field(description="The name of the worker.")
+    type: WorkerType
+    last_heartbeat_at: Optional[datetime] = Field(
+        default=None,
+        description="The time this worker last sent a heartbeat.",
+        alias="lastHeartbeatAt",
+    )
+    last_listener_established: Optional[datetime] = Field(
+        default=None,
+        description="The time this worker last sent a heartbeat.",
+        alias="lastListenerEstablished",
+    )
+    actions: Optional[List[StrictStr]] = Field(
+        default=None, description="The actions this worker can perform."
+    )
+    slots: Optional[List[SemaphoreSlots]] = Field(
+        default=None, description="The semaphore slot state for the worker."
+    )
+    recent_step_runs: Optional[List[RecentStepRuns]] = Field(
+        default=None,
+        description="The recent step runs for the worker.",
+        alias="recentStepRuns",
+    )
+    status: Optional[StrictStr] = Field(
+        default=None, description="The status of the worker."
+    )
+    max_runs: Optional[StrictInt] = Field(
+        default=None,
+        description="The maximum number of runs this worker can execute concurrently.",
+        alias="maxRuns",
+    )
+    available_runs: Optional[StrictInt] = Field(
+        default=None,
+        description="The number of runs this worker can execute concurrently.",
+        alias="availableRuns",
+    )
+    dispatcher_id: Optional[
+        Annotated[str, Field(min_length=36, strict=True, max_length=36)]
+    ] = Field(
+        default=None,
+        description="the id of the assigned dispatcher, in UUID format",
+        alias="dispatcherId",
+    )
+    labels: Optional[List[WorkerLabel]] = Field(
+        default=None, description="The current label state of the worker."
+    )
+    webhook_url: Optional[StrictStr] = Field(
+        default=None, description="The webhook URL for the worker.", alias="webhookUrl"
+    )
+    webhook_id: Optional[StrictStr] = Field(
+        default=None, description="The webhook ID for the worker.", alias="webhookId"
+    )
+    runtime_info: Optional[WorkerRuntimeInfo] = Field(default=None, alias="runtimeInfo")
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "name",
+        "type",
+        "lastHeartbeatAt",
+        "lastListenerEstablished",
+        "actions",
+        "slots",
+        "recentStepRuns",
+        "status",
+        "maxRuns",
+        "availableRuns",
+        "dispatcherId",
+        "labels",
+        "webhookUrl",
+        "webhookId",
+        "runtimeInfo",
+    ]
+
+    @field_validator("status")
+    def status_validate_enum(cls, value):
+        """Validates the enum"""
+        if value is None:
+            return value
+
+        if value not in set(["ACTIVE", "INACTIVE", "PAUSED"]):
+            raise ValueError(
+                "must be one of enum values ('ACTIVE', 'INACTIVE', 'PAUSED')"
+            )
+        return value
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of Worker from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in slots (list)
+        _items = []
+        if self.slots:
+            for _item_slots in self.slots:
+                if _item_slots:
+                    _items.append(_item_slots.to_dict())
+            _dict["slots"] = _items
+        # override the default output from pydantic by calling `to_dict()` of each item in recent_step_runs (list)
+        _items = []
+        if self.recent_step_runs:
+            for _item_recent_step_runs in self.recent_step_runs:
+                if _item_recent_step_runs:
+                    _items.append(_item_recent_step_runs.to_dict())
+            _dict["recentStepRuns"] = _items
+        # override the default output from pydantic by calling `to_dict()` of each item in labels (list)
+        _items = []
+        if self.labels:
+            for _item_labels in self.labels:
+                if _item_labels:
+                    _items.append(_item_labels.to_dict())
+            _dict["labels"] = _items
+        # override the default output from pydantic by calling `to_dict()` of runtime_info
+        if self.runtime_info:
+            _dict["runtimeInfo"] = self.runtime_info.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of Worker from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "name": obj.get("name"),
+                "type": obj.get("type"),
+                "lastHeartbeatAt": obj.get("lastHeartbeatAt"),
+                "lastListenerEstablished": obj.get("lastListenerEstablished"),
+                "actions": obj.get("actions"),
+                "slots": (
+                    [SemaphoreSlots.from_dict(_item) for _item in obj["slots"]]
+                    if obj.get("slots") is not None
+                    else None
+                ),
+                "recentStepRuns": (
+                    [RecentStepRuns.from_dict(_item) for _item in obj["recentStepRuns"]]
+                    if obj.get("recentStepRuns") is not None
+                    else None
+                ),
+                "status": obj.get("status"),
+                "maxRuns": obj.get("maxRuns"),
+                "availableRuns": obj.get("availableRuns"),
+                "dispatcherId": obj.get("dispatcherId"),
+                "labels": (
+                    [WorkerLabel.from_dict(_item) for _item in obj["labels"]]
+                    if obj.get("labels") is not None
+                    else None
+                ),
+                "webhookUrl": obj.get("webhookUrl"),
+                "webhookId": obj.get("webhookId"),
+                "runtimeInfo": (
+                    WorkerRuntimeInfo.from_dict(obj["runtimeInfo"])
+                    if obj.get("runtimeInfo") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_label.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_label.py
new file mode 100644
index 00000000..151febce
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_label.py
@@ -0,0 +1,102 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+
+
+class WorkerLabel(BaseModel):
+    """
+    WorkerLabel
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    key: StrictStr = Field(description="The key of the label.")
+    value: Optional[StrictStr] = Field(
+        default=None, description="The value of the label."
+    )
+    __properties: ClassVar[List[str]] = ["metadata", "key", "value"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkerLabel from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkerLabel from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "key": obj.get("key"),
+                "value": obj.get("value"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_list.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_list.py
new file mode 100644
index 00000000..bb02d792
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_list.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.worker import Worker
+
+
+class WorkerList(BaseModel):
+    """
+    WorkerList
+    """  # noqa: E501
+
+    pagination: Optional[PaginationResponse] = None
+    rows: Optional[List[Worker]] = None
+    __properties: ClassVar[List[str]] = ["pagination", "rows"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkerList from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkerList from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+                "rows": (
+                    [Worker.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_runtime_info.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_runtime_info.py
new file mode 100644
index 00000000..82db1f4a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_runtime_info.py
@@ -0,0 +1,103 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.worker_runtime_sdks import WorkerRuntimeSDKs
+
+
+class WorkerRuntimeInfo(BaseModel):
+    """
+    WorkerRuntimeInfo
+    """  # noqa: E501
+
+    sdk_version: Optional[StrictStr] = Field(default=None, alias="sdkVersion")
+    language: Optional[WorkerRuntimeSDKs] = None
+    language_version: Optional[StrictStr] = Field(default=None, alias="languageVersion")
+    os: Optional[StrictStr] = None
+    runtime_extra: Optional[StrictStr] = Field(default=None, alias="runtimeExtra")
+    __properties: ClassVar[List[str]] = [
+        "sdkVersion",
+        "language",
+        "languageVersion",
+        "os",
+        "runtimeExtra",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkerRuntimeInfo from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkerRuntimeInfo from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "sdkVersion": obj.get("sdkVersion"),
+                "language": obj.get("language"),
+                "languageVersion": obj.get("languageVersion"),
+                "os": obj.get("os"),
+                "runtimeExtra": obj.get("runtimeExtra"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_runtime_sdks.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_runtime_sdks.py
new file mode 100644
index 00000000..5716086e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_runtime_sdks.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class WorkerRuntimeSDKs(str, Enum):
+    """
+    WorkerRuntimeSDKs
+    """
+
+    """
+    allowed enum values
+    """
+    GOLANG = "GOLANG"
+    PYTHON = "PYTHON"
+    TYPESCRIPT = "TYPESCRIPT"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of WorkerRuntimeSDKs from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_type.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_type.py
new file mode 100644
index 00000000..81269d2b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/worker_type.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class WorkerType(str, Enum):
+    """
+    WorkerType
+    """
+
+    """
+    allowed enum values
+    """
+    SELFHOSTED = "SELFHOSTED"
+    MANAGED = "MANAGED"
+    WEBHOOK = "WEBHOOK"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of WorkerType from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow.py
new file mode 100644
index 00000000..f3107144
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow.py
@@ -0,0 +1,165 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.job import Job
+from hatchet_sdk.clients.rest.models.workflow_tag import WorkflowTag
+
+
+class Workflow(BaseModel):
+    """
+    Workflow
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    name: StrictStr = Field(description="The name of the workflow.")
+    description: Optional[StrictStr] = Field(
+        default=None, description="The description of the workflow."
+    )
+    is_paused: Optional[StrictBool] = Field(
+        default=None, description="Whether the workflow is paused.", alias="isPaused"
+    )
+    versions: Optional[List[WorkflowVersionMeta]] = None
+    tags: Optional[List[WorkflowTag]] = Field(
+        default=None, description="The tags of the workflow."
+    )
+    jobs: Optional[List[Job]] = Field(
+        default=None, description="The jobs of the workflow."
+    )
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "name",
+        "description",
+        "isPaused",
+        "versions",
+        "tags",
+        "jobs",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of Workflow from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in versions (list)
+        _items = []
+        if self.versions:
+            for _item_versions in self.versions:
+                if _item_versions:
+                    _items.append(_item_versions.to_dict())
+            _dict["versions"] = _items
+        # override the default output from pydantic by calling `to_dict()` of each item in tags (list)
+        _items = []
+        if self.tags:
+            for _item_tags in self.tags:
+                if _item_tags:
+                    _items.append(_item_tags.to_dict())
+            _dict["tags"] = _items
+        # override the default output from pydantic by calling `to_dict()` of each item in jobs (list)
+        _items = []
+        if self.jobs:
+            for _item_jobs in self.jobs:
+                if _item_jobs:
+                    _items.append(_item_jobs.to_dict())
+            _dict["jobs"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of Workflow from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "name": obj.get("name"),
+                "description": obj.get("description"),
+                "isPaused": obj.get("isPaused"),
+                "versions": (
+                    [WorkflowVersionMeta.from_dict(_item) for _item in obj["versions"]]
+                    if obj.get("versions") is not None
+                    else None
+                ),
+                "tags": (
+                    [WorkflowTag.from_dict(_item) for _item in obj["tags"]]
+                    if obj.get("tags") is not None
+                    else None
+                ),
+                "jobs": (
+                    [Job.from_dict(_item) for _item in obj["jobs"]]
+                    if obj.get("jobs") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
+
+
+from hatchet_sdk.clients.rest.models.workflow_version_meta import WorkflowVersionMeta
+
+# TODO: Rewrite to not use raise_errors
+Workflow.model_rebuild(raise_errors=False)
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_concurrency.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_concurrency.py
new file mode 100644
index 00000000..ce9d067e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_concurrency.py
@@ -0,0 +1,107 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.concurrency_limit_strategy import (
+    ConcurrencyLimitStrategy,
+)
+
+
+class WorkflowConcurrency(BaseModel):
+    """
+    WorkflowConcurrency
+    """  # noqa: E501
+
+    max_runs: StrictInt = Field(
+        description="The maximum number of concurrent workflow runs.", alias="maxRuns"
+    )
+    limit_strategy: ConcurrencyLimitStrategy = Field(
+        description="The strategy to use when the concurrency limit is reached.",
+        alias="limitStrategy",
+    )
+    get_concurrency_group: StrictStr = Field(
+        description="An action which gets the concurrency group for the WorkflowRun.",
+        alias="getConcurrencyGroup",
+    )
+    __properties: ClassVar[List[str]] = [
+        "maxRuns",
+        "limitStrategy",
+        "getConcurrencyGroup",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowConcurrency from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowConcurrency from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "maxRuns": obj.get("maxRuns"),
+                "limitStrategy": obj.get("limitStrategy"),
+                "getConcurrencyGroup": obj.get("getConcurrencyGroup"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_deployment_config.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_deployment_config.py
new file mode 100644
index 00000000..6ef1f60a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_deployment_config.py
@@ -0,0 +1,136 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.github_app_installation import (
+    GithubAppInstallation,
+)
+
+
+class WorkflowDeploymentConfig(BaseModel):
+    """
+    WorkflowDeploymentConfig
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    git_repo_name: StrictStr = Field(
+        description="The repository name.", alias="gitRepoName"
+    )
+    git_repo_owner: StrictStr = Field(
+        description="The repository owner.", alias="gitRepoOwner"
+    )
+    git_repo_branch: StrictStr = Field(
+        description="The repository branch.", alias="gitRepoBranch"
+    )
+    github_app_installation: Optional[GithubAppInstallation] = Field(
+        default=None,
+        description="The Github App installation.",
+        alias="githubAppInstallation",
+    )
+    github_app_installation_id: StrictStr = Field(
+        description="The id of the Github App installation.",
+        alias="githubAppInstallationId",
+    )
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "gitRepoName",
+        "gitRepoOwner",
+        "gitRepoBranch",
+        "githubAppInstallation",
+        "githubAppInstallationId",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowDeploymentConfig from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of github_app_installation
+        if self.github_app_installation:
+            _dict["githubAppInstallation"] = self.github_app_installation.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowDeploymentConfig from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "gitRepoName": obj.get("gitRepoName"),
+                "gitRepoOwner": obj.get("gitRepoOwner"),
+                "gitRepoBranch": obj.get("gitRepoBranch"),
+                "githubAppInstallation": (
+                    GithubAppInstallation.from_dict(obj["githubAppInstallation"])
+                    if obj.get("githubAppInstallation") is not None
+                    else None
+                ),
+                "githubAppInstallationId": obj.get("githubAppInstallationId"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_kind.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_kind.py
new file mode 100644
index 00000000..e258a048
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_kind.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class WorkflowKind(str, Enum):
+    """
+    WorkflowKind
+    """
+
+    """
+    allowed enum values
+    """
+    FUNCTION = "FUNCTION"
+    DURABLE = "DURABLE"
+    DAG = "DAG"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of WorkflowKind from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_list.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_list.py
new file mode 100644
index 00000000..9eb14aee
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_list.py
@@ -0,0 +1,120 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.workflow import Workflow
+
+
+class WorkflowList(BaseModel):
+    """
+    WorkflowList
+    """  # noqa: E501
+
+    metadata: Optional[APIResourceMeta] = None
+    rows: Optional[List[Workflow]] = None
+    pagination: Optional[PaginationResponse] = None
+    __properties: ClassVar[List[str]] = ["metadata", "rows", "pagination"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowList from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowList from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "rows": (
+                    [Workflow.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_metrics.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_metrics.py
new file mode 100644
index 00000000..8158e732
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_metrics.py
@@ -0,0 +1,97 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt
+from typing_extensions import Self
+
+
+class WorkflowMetrics(BaseModel):
+    """
+    WorkflowMetrics
+    """  # noqa: E501
+
+    group_key_runs_count: Optional[StrictInt] = Field(
+        default=None,
+        description="The number of runs for a specific group key (passed via filter)",
+        alias="groupKeyRunsCount",
+    )
+    group_key_count: Optional[StrictInt] = Field(
+        default=None,
+        description="The total number of concurrency group keys.",
+        alias="groupKeyCount",
+    )
+    __properties: ClassVar[List[str]] = ["groupKeyRunsCount", "groupKeyCount"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowMetrics from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowMetrics from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "groupKeyRunsCount": obj.get("groupKeyRunsCount"),
+                "groupKeyCount": obj.get("groupKeyCount"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run.py
new file mode 100644
index 00000000..903da30f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run.py
@@ -0,0 +1,188 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
+from typing_extensions import Annotated, Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.workflow_run_status import WorkflowRunStatus
+from hatchet_sdk.clients.rest.models.workflow_run_triggered_by import (
+    WorkflowRunTriggeredBy,
+)
+from hatchet_sdk.clients.rest.models.workflow_version import WorkflowVersion
+
+
+class WorkflowRun(BaseModel):
+    """
+    WorkflowRun
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    tenant_id: StrictStr = Field(alias="tenantId")
+    workflow_version_id: StrictStr = Field(alias="workflowVersionId")
+    workflow_version: Optional[WorkflowVersion] = Field(
+        default=None, alias="workflowVersion"
+    )
+    status: WorkflowRunStatus
+    display_name: Optional[StrictStr] = Field(default=None, alias="displayName")
+    job_runs: Optional[List[JobRun]] = Field(default=None, alias="jobRuns")
+    triggered_by: WorkflowRunTriggeredBy = Field(alias="triggeredBy")
+    input: Optional[Dict[str, Any]] = None
+    error: Optional[StrictStr] = None
+    started_at: Optional[datetime] = Field(default=None, alias="startedAt")
+    finished_at: Optional[datetime] = Field(default=None, alias="finishedAt")
+    duration: Optional[StrictInt] = None
+    parent_id: Optional[
+        Annotated[str, Field(min_length=36, strict=True, max_length=36)]
+    ] = Field(default=None, alias="parentId")
+    parent_step_run_id: Optional[
+        Annotated[str, Field(min_length=36, strict=True, max_length=36)]
+    ] = Field(default=None, alias="parentStepRunId")
+    additional_metadata: Optional[Dict[str, Any]] = Field(
+        default=None, alias="additionalMetadata"
+    )
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "tenantId",
+        "workflowVersionId",
+        "workflowVersion",
+        "status",
+        "displayName",
+        "jobRuns",
+        "triggeredBy",
+        "input",
+        "error",
+        "startedAt",
+        "finishedAt",
+        "duration",
+        "parentId",
+        "parentStepRunId",
+        "additionalMetadata",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowRun from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of workflow_version
+        if self.workflow_version:
+            _dict["workflowVersion"] = self.workflow_version.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in job_runs (list)
+        _items = []
+        if self.job_runs:
+            for _item_job_runs in self.job_runs:
+                if _item_job_runs:
+                    _items.append(_item_job_runs.to_dict())
+            _dict["jobRuns"] = _items
+        # override the default output from pydantic by calling `to_dict()` of triggered_by
+        if self.triggered_by:
+            _dict["triggeredBy"] = self.triggered_by.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowRun from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "tenantId": obj.get("tenantId"),
+                "workflowVersionId": obj.get("workflowVersionId"),
+                "workflowVersion": (
+                    WorkflowVersion.from_dict(obj["workflowVersion"])
+                    if obj.get("workflowVersion") is not None
+                    else None
+                ),
+                "status": obj.get("status"),
+                "displayName": obj.get("displayName"),
+                "jobRuns": (
+                    [JobRun.from_dict(_item) for _item in obj["jobRuns"]]
+                    if obj.get("jobRuns") is not None
+                    else None
+                ),
+                "triggeredBy": (
+                    WorkflowRunTriggeredBy.from_dict(obj["triggeredBy"])
+                    if obj.get("triggeredBy") is not None
+                    else None
+                ),
+                "input": obj.get("input"),
+                "error": obj.get("error"),
+                "startedAt": obj.get("startedAt"),
+                "finishedAt": obj.get("finishedAt"),
+                "duration": obj.get("duration"),
+                "parentId": obj.get("parentId"),
+                "parentStepRunId": obj.get("parentStepRunId"),
+                "additionalMetadata": obj.get("additionalMetadata"),
+            }
+        )
+        return _obj
+
+
+from hatchet_sdk.clients.rest.models.job_run import JobRun
+
+# TODO: Rewrite to not use raise_errors
+WorkflowRun.model_rebuild(raise_errors=False)
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_cancel200_response.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_cancel200_response.py
new file mode 100644
index 00000000..fbf545be
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_cancel200_response.py
@@ -0,0 +1,85 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Annotated, Self
+
+
+class WorkflowRunCancel200Response(BaseModel):
+    """
+    WorkflowRunCancel200Response
+    """  # noqa: E501
+
+    workflow_run_ids: Optional[
+        List[Annotated[str, Field(min_length=36, strict=True, max_length=36)]]
+    ] = Field(default=None, alias="workflowRunIds")
+    __properties: ClassVar[List[str]] = ["workflowRunIds"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowRunCancel200Response from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowRunCancel200Response from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"workflowRunIds": obj.get("workflowRunIds")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_list.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_list.py
new file mode 100644
index 00000000..a56d3feb
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_list.py
@@ -0,0 +1,110 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
+from hatchet_sdk.clients.rest.models.workflow_run import WorkflowRun
+
+
+class WorkflowRunList(BaseModel):
+    """
+    WorkflowRunList
+    """  # noqa: E501
+
+    rows: Optional[List[WorkflowRun]] = None
+    pagination: Optional[PaginationResponse] = None
+    __properties: ClassVar[List[str]] = ["rows", "pagination"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowRunList from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
+        _items = []
+        if self.rows:
+            for _item_rows in self.rows:
+                if _item_rows:
+                    _items.append(_item_rows.to_dict())
+            _dict["rows"] = _items
+        # override the default output from pydantic by calling `to_dict()` of pagination
+        if self.pagination:
+            _dict["pagination"] = self.pagination.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowRunList from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "rows": (
+                    [WorkflowRun.from_dict(_item) for _item in obj["rows"]]
+                    if obj.get("rows") is not None
+                    else None
+                ),
+                "pagination": (
+                    PaginationResponse.from_dict(obj["pagination"])
+                    if obj.get("pagination") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_order_by_direction.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_order_by_direction.py
new file mode 100644
index 00000000..4b499699
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_order_by_direction.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class WorkflowRunOrderByDirection(str, Enum):
+    """
+    WorkflowRunOrderByDirection
+    """
+
+    """
+    allowed enum values
+    """
+    ASC = "ASC"
+    DESC = "DESC"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of WorkflowRunOrderByDirection from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_order_by_field.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_order_by_field.py
new file mode 100644
index 00000000..bad42454
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_order_by_field.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class WorkflowRunOrderByField(str, Enum):
+    """
+    WorkflowRunOrderByField
+    """
+
+    """
+    allowed enum values
+    """
+    CREATEDAT = "createdAt"
+    STARTEDAT = "startedAt"
+    FINISHEDAT = "finishedAt"
+    DURATION = "duration"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of WorkflowRunOrderByField from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_shape.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_shape.py
new file mode 100644
index 00000000..426e7ef9
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_shape.py
@@ -0,0 +1,186 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from datetime import datetime
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
+from typing_extensions import Annotated, Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.job_run import JobRun
+from hatchet_sdk.clients.rest.models.workflow_run_status import WorkflowRunStatus
+from hatchet_sdk.clients.rest.models.workflow_run_triggered_by import (
+    WorkflowRunTriggeredBy,
+)
+from hatchet_sdk.clients.rest.models.workflow_version import WorkflowVersion
+
+
+class WorkflowRunShape(BaseModel):
+    """
+    WorkflowRunShape
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    tenant_id: StrictStr = Field(alias="tenantId")
+    workflow_id: Optional[StrictStr] = Field(default=None, alias="workflowId")
+    workflow_version_id: StrictStr = Field(alias="workflowVersionId")
+    workflow_version: Optional[WorkflowVersion] = Field(
+        default=None, alias="workflowVersion"
+    )
+    status: WorkflowRunStatus
+    display_name: Optional[StrictStr] = Field(default=None, alias="displayName")
+    job_runs: Optional[List[JobRun]] = Field(default=None, alias="jobRuns")
+    triggered_by: WorkflowRunTriggeredBy = Field(alias="triggeredBy")
+    input: Optional[Dict[str, Any]] = None
+    error: Optional[StrictStr] = None
+    started_at: Optional[datetime] = Field(default=None, alias="startedAt")
+    finished_at: Optional[datetime] = Field(default=None, alias="finishedAt")
+    duration: Optional[StrictInt] = None
+    parent_id: Optional[
+        Annotated[str, Field(min_length=36, strict=True, max_length=36)]
+    ] = Field(default=None, alias="parentId")
+    parent_step_run_id: Optional[
+        Annotated[str, Field(min_length=36, strict=True, max_length=36)]
+    ] = Field(default=None, alias="parentStepRunId")
+    additional_metadata: Optional[Dict[str, Any]] = Field(
+        default=None, alias="additionalMetadata"
+    )
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "tenantId",
+        "workflowId",
+        "workflowVersionId",
+        "workflowVersion",
+        "status",
+        "displayName",
+        "jobRuns",
+        "triggeredBy",
+        "input",
+        "error",
+        "startedAt",
+        "finishedAt",
+        "duration",
+        "parentId",
+        "parentStepRunId",
+        "additionalMetadata",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowRunShape from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of workflow_version
+        if self.workflow_version:
+            _dict["workflowVersion"] = self.workflow_version.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in job_runs (list)
+        _items = []
+        if self.job_runs:
+            for _item_job_runs in self.job_runs:
+                if _item_job_runs:
+                    _items.append(_item_job_runs.to_dict())
+            _dict["jobRuns"] = _items
+        # override the default output from pydantic by calling `to_dict()` of triggered_by
+        if self.triggered_by:
+            _dict["triggeredBy"] = self.triggered_by.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowRunShape from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "tenantId": obj.get("tenantId"),
+                "workflowId": obj.get("workflowId"),
+                "workflowVersionId": obj.get("workflowVersionId"),
+                "workflowVersion": (
+                    WorkflowVersion.from_dict(obj["workflowVersion"])
+                    if obj.get("workflowVersion") is not None
+                    else None
+                ),
+                "status": obj.get("status"),
+                "displayName": obj.get("displayName"),
+                "jobRuns": (
+                    [JobRun.from_dict(_item) for _item in obj["jobRuns"]]
+                    if obj.get("jobRuns") is not None
+                    else None
+                ),
+                "triggeredBy": (
+                    WorkflowRunTriggeredBy.from_dict(obj["triggeredBy"])
+                    if obj.get("triggeredBy") is not None
+                    else None
+                ),
+                "input": obj.get("input"),
+                "error": obj.get("error"),
+                "startedAt": obj.get("startedAt"),
+                "finishedAt": obj.get("finishedAt"),
+                "duration": obj.get("duration"),
+                "parentId": obj.get("parentId"),
+                "parentStepRunId": obj.get("parentStepRunId"),
+                "additionalMetadata": obj.get("additionalMetadata"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_status.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_status.py
new file mode 100644
index 00000000..06bdee87
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_status.py
@@ -0,0 +1,42 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+from enum import Enum
+
+from typing_extensions import Self
+
+
+class WorkflowRunStatus(str, Enum):
+    """
+    WorkflowRunStatus
+    """
+
+    """
+    allowed enum values
+    """
+    PENDING = "PENDING"
+    RUNNING = "RUNNING"
+    SUCCEEDED = "SUCCEEDED"
+    FAILED = "FAILED"
+    CANCELLED = "CANCELLED"
+    QUEUED = "QUEUED"
+    BACKOFF = "BACKOFF"
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Self:
+        """Create an instance of WorkflowRunStatus from a JSON string"""
+        return cls(json.loads(json_str))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_triggered_by.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_triggered_by.py
new file mode 100644
index 00000000..8cbe1c11
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_run_triggered_by.py
@@ -0,0 +1,112 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+
+
+class WorkflowRunTriggeredBy(BaseModel):
+    """
+    WorkflowRunTriggeredBy
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    parent_workflow_run_id: Optional[StrictStr] = Field(
+        default=None, alias="parentWorkflowRunId"
+    )
+    event_id: Optional[StrictStr] = Field(default=None, alias="eventId")
+    cron_parent_id: Optional[StrictStr] = Field(default=None, alias="cronParentId")
+    cron_schedule: Optional[StrictStr] = Field(default=None, alias="cronSchedule")
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "parentWorkflowRunId",
+        "eventId",
+        "cronParentId",
+        "cronSchedule",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowRunTriggeredBy from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowRunTriggeredBy from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "parentWorkflowRunId": obj.get("parentWorkflowRunId"),
+                "eventId": obj.get("eventId"),
+                "cronParentId": obj.get("cronParentId"),
+                "cronSchedule": obj.get("cronSchedule"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_runs_cancel_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_runs_cancel_request.py
new file mode 100644
index 00000000..d5557cda
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_runs_cancel_request.py
@@ -0,0 +1,85 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field
+from typing_extensions import Annotated, Self
+
+
+class WorkflowRunsCancelRequest(BaseModel):
+    """
+    WorkflowRunsCancelRequest
+    """  # noqa: E501
+
+    workflow_run_ids: List[
+        Annotated[str, Field(min_length=36, strict=True, max_length=36)]
+    ] = Field(alias="workflowRunIds")
+    __properties: ClassVar[List[str]] = ["workflowRunIds"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowRunsCancelRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowRunsCancelRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"workflowRunIds": obj.get("workflowRunIds")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_runs_metrics.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_runs_metrics.py
new file mode 100644
index 00000000..71b6351b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_runs_metrics.py
@@ -0,0 +1,94 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict
+from typing_extensions import Self
+
+
+class WorkflowRunsMetrics(BaseModel):
+    """
+    WorkflowRunsMetrics
+    """  # noqa: E501
+
+    counts: Optional[Dict[str, Any]] = None
+    __properties: ClassVar[List[str]] = ["counts"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowRunsMetrics from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of counts
+        if self.counts:
+            _dict["counts"] = self.counts.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowRunsMetrics from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "counts": (
+                    WorkflowRunsMetricsCounts.from_dict(obj["counts"])
+                    if obj.get("counts") is not None
+                    else None
+                )
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_runs_metrics_counts.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_runs_metrics_counts.py
new file mode 100644
index 00000000..e8c92256
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_runs_metrics_counts.py
@@ -0,0 +1,104 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt
+from typing_extensions import Self
+
+
+class WorkflowRunsMetricsCounts(BaseModel):
+    """
+    WorkflowRunsMetricsCounts
+    """  # noqa: E501
+
+    pending: Optional[StrictInt] = Field(default=None, alias="PENDING")
+    running: Optional[StrictInt] = Field(default=None, alias="RUNNING")
+    succeeded: Optional[StrictInt] = Field(default=None, alias="SUCCEEDED")
+    failed: Optional[StrictInt] = Field(default=None, alias="FAILED")
+    queued: Optional[StrictInt] = Field(default=None, alias="QUEUED")
+    cancelled: Optional[StrictInt] = Field(default=None, alias="CANCELLED")
+    __properties: ClassVar[List[str]] = [
+        "PENDING",
+        "RUNNING",
+        "SUCCEEDED",
+        "FAILED",
+        "QUEUED",
+        "CANCELLED",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowRunsMetricsCounts from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowRunsMetricsCounts from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "PENDING": obj.get("PENDING"),
+                "RUNNING": obj.get("RUNNING"),
+                "SUCCEEDED": obj.get("SUCCEEDED"),
+                "FAILED": obj.get("FAILED"),
+                "QUEUED": obj.get("QUEUED"),
+                "CANCELLED": obj.get("CANCELLED"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_tag.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_tag.py
new file mode 100644
index 00000000..fcd3423a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_tag.py
@@ -0,0 +1,84 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class WorkflowTag(BaseModel):
+    """
+    WorkflowTag
+    """  # noqa: E501
+
+    name: StrictStr = Field(description="The name of the workflow.")
+    color: StrictStr = Field(description="The description of the workflow.")
+    __properties: ClassVar[List[str]] = ["name", "color"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowTag from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowTag from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"name": obj.get("name"), "color": obj.get("color")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_trigger_cron_ref.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_trigger_cron_ref.py
new file mode 100644
index 00000000..1750e659
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_trigger_cron_ref.py
@@ -0,0 +1,86 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, StrictStr
+from typing_extensions import Self
+
+
+class WorkflowTriggerCronRef(BaseModel):
+    """
+    WorkflowTriggerCronRef
+    """  # noqa: E501
+
+    parent_id: Optional[StrictStr] = None
+    cron: Optional[StrictStr] = None
+    __properties: ClassVar[List[str]] = ["parent_id", "cron"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowTriggerCronRef from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowTriggerCronRef from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {"parent_id": obj.get("parent_id"), "cron": obj.get("cron")}
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_trigger_event_ref.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_trigger_event_ref.py
new file mode 100644
index 00000000..cfabbe02
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_trigger_event_ref.py
@@ -0,0 +1,86 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, StrictStr
+from typing_extensions import Self
+
+
+class WorkflowTriggerEventRef(BaseModel):
+    """
+    WorkflowTriggerEventRef
+    """  # noqa: E501
+
+    parent_id: Optional[StrictStr] = None
+    event_key: Optional[StrictStr] = None
+    __properties: ClassVar[List[str]] = ["parent_id", "event_key"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowTriggerEventRef from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowTriggerEventRef from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {"parent_id": obj.get("parent_id"), "event_key": obj.get("event_key")}
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_triggers.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_triggers.py
new file mode 100644
index 00000000..fd2f07ef
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_triggers.py
@@ -0,0 +1,141 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.workflow_trigger_cron_ref import (
+    WorkflowTriggerCronRef,
+)
+from hatchet_sdk.clients.rest.models.workflow_trigger_event_ref import (
+    WorkflowTriggerEventRef,
+)
+
+
+class WorkflowTriggers(BaseModel):
+    """
+    WorkflowTriggers
+    """  # noqa: E501
+
+    metadata: Optional[APIResourceMeta] = None
+    workflow_version_id: Optional[StrictStr] = None
+    tenant_id: Optional[StrictStr] = None
+    events: Optional[List[WorkflowTriggerEventRef]] = None
+    crons: Optional[List[WorkflowTriggerCronRef]] = None
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "workflow_version_id",
+        "tenant_id",
+        "events",
+        "crons",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowTriggers from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in events (list)
+        _items = []
+        if self.events:
+            for _item_events in self.events:
+                if _item_events:
+                    _items.append(_item_events.to_dict())
+            _dict["events"] = _items
+        # override the default output from pydantic by calling `to_dict()` of each item in crons (list)
+        _items = []
+        if self.crons:
+            for _item_crons in self.crons:
+                if _item_crons:
+                    _items.append(_item_crons.to_dict())
+            _dict["crons"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowTriggers from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "workflow_version_id": obj.get("workflow_version_id"),
+                "tenant_id": obj.get("tenant_id"),
+                "events": (
+                    [
+                        WorkflowTriggerEventRef.from_dict(_item)
+                        for _item in obj["events"]
+                    ]
+                    if obj.get("events") is not None
+                    else None
+                ),
+                "crons": (
+                    [WorkflowTriggerCronRef.from_dict(_item) for _item in obj["crons"]]
+                    if obj.get("crons") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_update_request.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_update_request.py
new file mode 100644
index 00000000..5ec56835
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_update_request.py
@@ -0,0 +1,85 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictBool
+from typing_extensions import Self
+
+
+class WorkflowUpdateRequest(BaseModel):
+    """
+    WorkflowUpdateRequest
+    """  # noqa: E501
+
+    is_paused: Optional[StrictBool] = Field(
+        default=None, description="Whether the workflow is paused.", alias="isPaused"
+    )
+    __properties: ClassVar[List[str]] = ["isPaused"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowUpdateRequest from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowUpdateRequest from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"isPaused": obj.get("isPaused")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_version.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_version.py
new file mode 100644
index 00000000..47554e56
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_version.py
@@ -0,0 +1,170 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+from hatchet_sdk.clients.rest.models.job import Job
+from hatchet_sdk.clients.rest.models.workflow import Workflow
+from hatchet_sdk.clients.rest.models.workflow_concurrency import WorkflowConcurrency
+from hatchet_sdk.clients.rest.models.workflow_triggers import WorkflowTriggers
+
+
+class WorkflowVersion(BaseModel):
+    """
+    WorkflowVersion
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    version: StrictStr = Field(description="The version of the workflow.")
+    order: StrictInt
+    workflow_id: StrictStr = Field(alias="workflowId")
+    sticky: Optional[StrictStr] = Field(
+        default=None, description="The sticky strategy of the workflow."
+    )
+    default_priority: Optional[StrictInt] = Field(
+        default=None,
+        description="The default priority of the workflow.",
+        alias="defaultPriority",
+    )
+    workflow: Optional[Workflow] = None
+    concurrency: Optional[WorkflowConcurrency] = None
+    triggers: Optional[WorkflowTriggers] = None
+    schedule_timeout: Optional[StrictStr] = Field(default=None, alias="scheduleTimeout")
+    jobs: Optional[List[Job]] = None
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "version",
+        "order",
+        "workflowId",
+        "sticky",
+        "defaultPriority",
+        "workflow",
+        "concurrency",
+        "triggers",
+        "scheduleTimeout",
+        "jobs",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowVersion from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of workflow
+        if self.workflow:
+            _dict["workflow"] = self.workflow.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of concurrency
+        if self.concurrency:
+            _dict["concurrency"] = self.concurrency.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of triggers
+        if self.triggers:
+            _dict["triggers"] = self.triggers.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of each item in jobs (list)
+        _items = []
+        if self.jobs:
+            for _item_jobs in self.jobs:
+                if _item_jobs:
+                    _items.append(_item_jobs.to_dict())
+            _dict["jobs"] = _items
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowVersion from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "version": obj.get("version"),
+                "order": obj.get("order"),
+                "workflowId": obj.get("workflowId"),
+                "sticky": obj.get("sticky"),
+                "defaultPriority": obj.get("defaultPriority"),
+                "workflow": (
+                    Workflow.from_dict(obj["workflow"])
+                    if obj.get("workflow") is not None
+                    else None
+                ),
+                "concurrency": (
+                    WorkflowConcurrency.from_dict(obj["concurrency"])
+                    if obj.get("concurrency") is not None
+                    else None
+                ),
+                "triggers": (
+                    WorkflowTriggers.from_dict(obj["triggers"])
+                    if obj.get("triggers") is not None
+                    else None
+                ),
+                "scheduleTimeout": obj.get("scheduleTimeout"),
+                "jobs": (
+                    [Job.from_dict(_item) for _item in obj["jobs"]]
+                    if obj.get("jobs") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_version_concurrency.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_version_concurrency.py
new file mode 100644
index 00000000..d9893920
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_version_concurrency.py
@@ -0,0 +1,114 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, Field, StrictInt, StrictStr, field_validator
+from typing_extensions import Self
+
+
+class WorkflowVersionConcurrency(BaseModel):
+    """
+    WorkflowVersionConcurrency
+    """  # noqa: E501
+
+    max_runs: StrictInt = Field(
+        description="The maximum number of concurrent workflow runs.", alias="maxRuns"
+    )
+    limit_strategy: StrictStr = Field(
+        description="The strategy to use when the concurrency limit is reached.",
+        alias="limitStrategy",
+    )
+    get_concurrency_group: StrictStr = Field(
+        description="An action which gets the concurrency group for the WorkflowRun.",
+        alias="getConcurrencyGroup",
+    )
+    __properties: ClassVar[List[str]] = [
+        "maxRuns",
+        "limitStrategy",
+        "getConcurrencyGroup",
+    ]
+
+    @field_validator("limit_strategy")
+    def limit_strategy_validate_enum(cls, value):
+        """Validates the enum"""
+        if value not in set(
+            ["CANCEL_IN_PROGRESS", "DROP_NEWEST", "QUEUE_NEWEST", "GROUP_ROUND_ROBIN"]
+        ):
+            raise ValueError(
+                "must be one of enum values ('CANCEL_IN_PROGRESS', 'DROP_NEWEST', 'QUEUE_NEWEST', 'GROUP_ROUND_ROBIN')"
+            )
+        return value
+
+    model_config = {
+        "populate_by_name": True,
+        "validate_assignment": True,
+        "protected_namespaces": (),
+    }
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowVersionConcurrency from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowVersionConcurrency from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "maxRuns": obj.get("maxRuns"),
+                "limitStrategy": obj.get("limitStrategy"),
+                "getConcurrencyGroup": obj.get("getConcurrencyGroup"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_version_definition.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_version_definition.py
new file mode 100644
index 00000000..3f44c23a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_version_definition.py
@@ -0,0 +1,85 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing_extensions import Self
+
+
+class WorkflowVersionDefinition(BaseModel):
+    """
+    WorkflowVersionDefinition
+    """  # noqa: E501
+
+    raw_definition: StrictStr = Field(
+        description="The raw YAML definition of the workflow.", alias="rawDefinition"
+    )
+    __properties: ClassVar[List[str]] = ["rawDefinition"]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowVersionDefinition from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowVersionDefinition from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate({"rawDefinition": obj.get("rawDefinition")})
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_version_meta.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_version_meta.py
new file mode 100644
index 00000000..be2c5672
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_version_meta.py
@@ -0,0 +1,123 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
+from typing_extensions import Self
+
+from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
+
+
+class WorkflowVersionMeta(BaseModel):
+    """
+    WorkflowVersionMeta
+    """  # noqa: E501
+
+    metadata: APIResourceMeta
+    version: StrictStr = Field(description="The version of the workflow.")
+    order: StrictInt
+    workflow_id: StrictStr = Field(alias="workflowId")
+    workflow: Optional[Workflow] = None
+    __properties: ClassVar[List[str]] = [
+        "metadata",
+        "version",
+        "order",
+        "workflowId",
+        "workflow",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowVersionMeta from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        # override the default output from pydantic by calling `to_dict()` of metadata
+        if self.metadata:
+            _dict["metadata"] = self.metadata.to_dict()
+        # override the default output from pydantic by calling `to_dict()` of workflow
+        if self.workflow:
+            _dict["workflow"] = self.workflow.to_dict()
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowVersionMeta from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "metadata": (
+                    APIResourceMeta.from_dict(obj["metadata"])
+                    if obj.get("metadata") is not None
+                    else None
+                ),
+                "version": obj.get("version"),
+                "order": obj.get("order"),
+                "workflowId": obj.get("workflowId"),
+                "workflow": (
+                    Workflow.from_dict(obj["workflow"])
+                    if obj.get("workflow") is not None
+                    else None
+                ),
+            }
+        )
+        return _obj
+
+
+from hatchet_sdk.clients.rest.models.workflow import Workflow
+
+# TODO: Rewrite to not use raise_errors
+WorkflowVersionMeta.model_rebuild(raise_errors=False)
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_workers_count.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_workers_count.py
new file mode 100644
index 00000000..c42edbf5
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/models/workflow_workers_count.py
@@ -0,0 +1,95 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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 json
+import pprint
+import re  # noqa: F401
+from typing import Any, ClassVar, Dict, List, Optional, Set
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
+from typing_extensions import Self
+
+
+class WorkflowWorkersCount(BaseModel):
+    """
+    WorkflowWorkersCount
+    """  # noqa: E501
+
+    free_slot_count: Optional[StrictInt] = Field(default=None, alias="freeSlotCount")
+    max_slot_count: Optional[StrictInt] = Field(default=None, alias="maxSlotCount")
+    workflow_run_id: Optional[StrictStr] = Field(default=None, alias="workflowRunId")
+    __properties: ClassVar[List[str]] = [
+        "freeSlotCount",
+        "maxSlotCount",
+        "workflowRunId",
+    ]
+
+    model_config = ConfigDict(
+        populate_by_name=True,
+        validate_assignment=True,
+        protected_namespaces=(),
+    )
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.model_dump(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> Optional[Self]:
+        """Create an instance of WorkflowWorkersCount from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self) -> Dict[str, Any]:
+        """Return the dictionary representation of the model using alias.
+
+        This has the following differences from calling pydantic's
+        `self.model_dump(by_alias=True)`:
+
+        * `None` is only added to the output dict for nullable fields that
+          were set at model initialization. Other fields with value `None`
+          are ignored.
+        """
+        excluded_fields: Set[str] = set([])
+
+        _dict = self.model_dump(
+            by_alias=True,
+            exclude=excluded_fields,
+            exclude_none=True,
+        )
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+        """Create an instance of WorkflowWorkersCount from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return cls.model_validate(obj)
+
+        _obj = cls.model_validate(
+            {
+                "freeSlotCount": obj.get("freeSlotCount"),
+                "maxSlotCount": obj.get("maxSlotCount"),
+                "workflowRunId": obj.get("workflowRunId"),
+            }
+        )
+        return _obj
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/rest.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/rest.py
new file mode 100644
index 00000000..56286e14
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/rest.py
@@ -0,0 +1,187 @@
+# coding: utf-8
+
+"""
+    Hatchet API
+
+    The Hatchet API
+
+    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
+import json
+import re
+import ssl
+from typing import Optional, Union
+
+import aiohttp
+import aiohttp_retry
+
+from hatchet_sdk.clients.rest.exceptions import ApiException, ApiValueError
+
+RESTResponseType = aiohttp.ClientResponse
+
+ALLOW_RETRY_METHODS = frozenset({"DELETE", "GET", "HEAD", "OPTIONS", "PUT", "TRACE"})
+
+
+class RESTResponse(io.IOBase):
+
+    def __init__(self, resp) -> None:
+        self.response = resp
+        self.status = resp.status
+        self.reason = resp.reason
+        self.data = None
+
+    async def read(self):
+        if self.data is None:
+            self.data = await self.response.read()
+        return self.data
+
+    def getheaders(self):
+        """Returns a CIMultiDictProxy of the response headers."""
+        return self.response.headers
+
+    def getheader(self, name, default=None):
+        """Returns a given response header."""
+        return self.response.headers.get(name, default)
+
+
+class RESTClientObject:
+
+    def __init__(self, configuration) -> None:
+
+        # maxsize is number of requests to host that are allowed in parallel
+        maxsize = configuration.connection_pool_maxsize
+
+        ssl_context = ssl.create_default_context(cafile=configuration.ssl_ca_cert)
+        if configuration.cert_file:
+            ssl_context.load_cert_chain(
+                configuration.cert_file, keyfile=configuration.key_file
+            )
+
+        if not configuration.verify_ssl:
+            ssl_context.check_hostname = False
+            ssl_context.verify_mode = ssl.CERT_NONE
+
+        connector = aiohttp.TCPConnector(limit=maxsize, ssl=ssl_context)
+
+        self.proxy = configuration.proxy
+        self.proxy_headers = configuration.proxy_headers
+
+        # https pool manager
+        self.pool_manager = aiohttp.ClientSession(connector=connector, trust_env=True)
+
+        retries = configuration.retries
+        self.retry_client: Optional[aiohttp_retry.RetryClient]
+        if retries is not None:
+            self.retry_client = aiohttp_retry.RetryClient(
+                client_session=self.pool_manager,
+                retry_options=aiohttp_retry.ExponentialRetry(
+                    attempts=retries, factor=2.0, start_timeout=0.1, max_timeout=120.0
+                ),
+            )
+        else:
+            self.retry_client = None
+
+    async def close(self):
+        await self.pool_manager.close()
+        if self.retry_client is not None:
+            await self.retry_client.close()
+
+    async def request(
+        self,
+        method,
+        url,
+        headers=None,
+        body=None,
+        post_params=None,
+        _request_timeout=None,
+    ):
+        """Execute request
+
+        :param method: http request method
+        :param url: http request url
+        :param headers: http request headers
+        :param body: request json body, for `application/json`
+        :param post_params: request post parameters,
+                            `application/x-www-form-urlencoded`
+                            and `multipart/form-data`
+        :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.
+        """
+        method = method.upper()
+        assert method in ["GET", "HEAD", "DELETE", "POST", "PUT", "PATCH", "OPTIONS"]
+
+        if post_params and body:
+            raise ApiValueError(
+                "body parameter cannot be used with post_params parameter."
+            )
+
+        post_params = post_params or {}
+        headers = headers or {}
+        # url already contains the URL query string
+        timeout = _request_timeout or 5 * 60
+
+        if "Content-Type" not in headers:
+            headers["Content-Type"] = "application/json"
+
+        args = {"method": method, "url": url, "timeout": timeout, "headers": headers}
+
+        if self.proxy:
+            args["proxy"] = self.proxy
+        if self.proxy_headers:
+            args["proxy_headers"] = self.proxy_headers
+
+        # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
+        if method in ["POST", "PUT", "PATCH", "OPTIONS", "DELETE"]:
+            if re.search("json", headers["Content-Type"], re.IGNORECASE):
+                if body is not None:
+                    body = json.dumps(body)
+                args["data"] = body
+            elif headers["Content-Type"] == "application/x-www-form-urlencoded":
+                args["data"] = aiohttp.FormData(post_params)
+            elif headers["Content-Type"] == "multipart/form-data":
+                # must del headers['Content-Type'], or the correct
+                # Content-Type which generated by aiohttp
+                del headers["Content-Type"]
+                data = aiohttp.FormData()
+                for param in post_params:
+                    k, v = param
+                    if isinstance(v, tuple) and len(v) == 3:
+                        data.add_field(k, value=v[1], filename=v[0], content_type=v[2])
+                    else:
+                        # Ensures that dict objects are serialized
+                        if isinstance(v, dict):
+                            v = json.dumps(v)
+                        elif isinstance(v, int):
+                            v = str(v)
+                        data.add_field(k, v)
+                args["data"] = data
+
+            # Pass a `bytes` or `str` parameter directly in the body to support
+            # other content types than Json when `body` argument is provided
+            # in serialized form
+            elif isinstance(body, str) or isinstance(body, bytes):
+                args["data"] = body
+            else:
+                # Cannot generate the request from given parameters
+                msg = """Cannot prepare a request message for provided
+                         arguments. Please check that your arguments match
+                         declared content type."""
+                raise ApiException(status=0, reason=msg)
+
+        pool_manager: Union[aiohttp.ClientSession, aiohttp_retry.RetryClient]
+        if self.retry_client is not None and method in ALLOW_RETRY_METHODS:
+            pool_manager = self.retry_client
+        else:
+            pool_manager = self.pool_manager
+
+        r = await pool_manager.request(**args)
+
+        return RESTResponse(r)
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/tenacity_utils.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/tenacity_utils.py
new file mode 100644
index 00000000..377266a1
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest/tenacity_utils.py
@@ -0,0 +1,39 @@
+from typing import Callable, ParamSpec, TypeVar
+
+import grpc
+import tenacity
+
+from hatchet_sdk.logger import logger
+
+P = ParamSpec("P")
+R = TypeVar("R")
+
+
+def tenacity_retry(func: Callable[P, R]) -> Callable[P, R]:
+    return tenacity.retry(
+        reraise=True,
+        wait=tenacity.wait_exponential_jitter(),
+        stop=tenacity.stop_after_attempt(5),
+        before_sleep=tenacity_alert_retry,
+        retry=tenacity.retry_if_exception(tenacity_should_retry),
+    )(func)
+
+
+def tenacity_alert_retry(retry_state: tenacity.RetryCallState) -> None:
+    """Called between tenacity retries."""
+    logger.debug(
+        f"Retrying {retry_state.fn}: attempt "
+        f"{retry_state.attempt_number} ended with: {retry_state.outcome}",
+    )
+
+
+def tenacity_should_retry(ex: Exception) -> bool:
+    if isinstance(ex, (grpc.aio.AioRpcError, grpc.RpcError)):
+        if ex.code() in [
+            grpc.StatusCode.UNIMPLEMENTED,
+            grpc.StatusCode.NOT_FOUND,
+        ]:
+            return False
+        return True
+    else:
+        return False
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest_client.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest_client.py
new file mode 100644
index 00000000..f6458e5a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/rest_client.py
@@ -0,0 +1,611 @@
+import asyncio
+import atexit
+import datetime
+import threading
+from typing import Any, Coroutine, List
+
+from pydantic import StrictInt
+
+from hatchet_sdk.clients.rest.api.event_api import EventApi
+from hatchet_sdk.clients.rest.api.log_api import LogApi
+from hatchet_sdk.clients.rest.api.step_run_api import StepRunApi
+from hatchet_sdk.clients.rest.api.workflow_api import WorkflowApi
+from hatchet_sdk.clients.rest.api.workflow_run_api import WorkflowRunApi
+from hatchet_sdk.clients.rest.api.workflow_runs_api import WorkflowRunsApi
+from hatchet_sdk.clients.rest.api_client import ApiClient
+from hatchet_sdk.clients.rest.configuration import Configuration
+from hatchet_sdk.clients.rest.models import TriggerWorkflowRunRequest
+from hatchet_sdk.clients.rest.models.create_cron_workflow_trigger_request import (
+    CreateCronWorkflowTriggerRequest,
+)
+from hatchet_sdk.clients.rest.models.cron_workflows import CronWorkflows
+from hatchet_sdk.clients.rest.models.cron_workflows_order_by_field import (
+    CronWorkflowsOrderByField,
+)
+from hatchet_sdk.clients.rest.models.event_list import EventList
+from hatchet_sdk.clients.rest.models.event_order_by_direction import (
+    EventOrderByDirection,
+)
+from hatchet_sdk.clients.rest.models.event_order_by_field import EventOrderByField
+from hatchet_sdk.clients.rest.models.log_line_level import LogLineLevel
+from hatchet_sdk.clients.rest.models.log_line_list import LogLineList
+from hatchet_sdk.clients.rest.models.log_line_order_by_direction import (
+    LogLineOrderByDirection,
+)
+from hatchet_sdk.clients.rest.models.log_line_order_by_field import LogLineOrderByField
+from hatchet_sdk.clients.rest.models.replay_event_request import ReplayEventRequest
+from hatchet_sdk.clients.rest.models.replay_workflow_runs_request import (
+    ReplayWorkflowRunsRequest,
+)
+from hatchet_sdk.clients.rest.models.replay_workflow_runs_response import (
+    ReplayWorkflowRunsResponse,
+)
+from hatchet_sdk.clients.rest.models.schedule_workflow_run_request import (
+    ScheduleWorkflowRunRequest,
+)
+from hatchet_sdk.clients.rest.models.scheduled_workflows import ScheduledWorkflows
+from hatchet_sdk.clients.rest.models.scheduled_workflows_order_by_field import (
+    ScheduledWorkflowsOrderByField,
+)
+from hatchet_sdk.clients.rest.models.workflow import Workflow
+from hatchet_sdk.clients.rest.models.workflow_kind import WorkflowKind
+from hatchet_sdk.clients.rest.models.workflow_list import WorkflowList
+from hatchet_sdk.clients.rest.models.workflow_run import WorkflowRun
+from hatchet_sdk.clients.rest.models.workflow_run_cancel200_response import (
+    WorkflowRunCancel200Response,
+)
+from hatchet_sdk.clients.rest.models.workflow_run_list import WorkflowRunList
+from hatchet_sdk.clients.rest.models.workflow_run_order_by_direction import (
+    WorkflowRunOrderByDirection,
+)
+from hatchet_sdk.clients.rest.models.workflow_run_order_by_field import (
+    WorkflowRunOrderByField,
+)
+from hatchet_sdk.clients.rest.models.workflow_run_status import WorkflowRunStatus
+from hatchet_sdk.clients.rest.models.workflow_runs_cancel_request import (
+    WorkflowRunsCancelRequest,
+)
+from hatchet_sdk.clients.rest.models.workflow_version import WorkflowVersion
+
+
+class AsyncRestApi:
+    def __init__(self, host: str, api_key: str, tenant_id: str):
+        self.tenant_id = tenant_id
+
+        self.config = Configuration(
+            host=host,
+            access_token=api_key,
+        )
+
+        self._api_client = None
+        self._workflow_api = None
+        self._workflow_run_api = None
+        self._step_run_api = None
+        self._event_api = None
+        self._log_api = None
+
+    @property
+    def api_client(self):
+        if self._api_client is None:
+            self._api_client = ApiClient(configuration=self.config)
+        return self._api_client
+
+    @property
+    def workflow_api(self):
+        if self._workflow_api is None:
+            self._workflow_api = WorkflowApi(self.api_client)
+        return self._workflow_api
+
+    @property
+    def workflow_run_api(self):
+        if self._workflow_run_api is None:
+            self._workflow_run_api = WorkflowRunApi(self.api_client)
+        return self._workflow_run_api
+
+    @property
+    def step_run_api(self):
+        if self._step_run_api is None:
+            self._step_run_api = StepRunApi(self.api_client)
+        return self._step_run_api
+
+    @property
+    def event_api(self):
+        if self._event_api is None:
+            self._event_api = EventApi(self.api_client)
+        return self._event_api
+
+    @property
+    def log_api(self):
+        if self._log_api is None:
+            self._log_api = LogApi(self.api_client)
+        return self._log_api
+
+    async def close(self):
+        # Ensure the aiohttp client session is closed
+        if self._api_client is not None:
+            await self._api_client.close()
+
+    async def workflow_list(self) -> WorkflowList:
+        return await self.workflow_api.workflow_list(
+            tenant=self.tenant_id,
+        )
+
+    async def workflow_get(self, workflow_id: str) -> Workflow:
+        return await self.workflow_api.workflow_get(
+            workflow=workflow_id,
+        )
+
+    async def workflow_version_get(
+        self, workflow_id: str, version: str | None = None
+    ) -> WorkflowVersion:
+        return await self.workflow_api.workflow_version_get(
+            workflow=workflow_id,
+            version=version,
+        )
+
+    async def workflow_run_list(
+        self,
+        workflow_id: str | None = None,
+        offset: int | None = None,
+        limit: int | None = None,
+        event_id: str | None = None,
+        parent_workflow_run_id: str | None = None,
+        parent_step_run_id: str | None = None,
+        statuses: list[WorkflowRunStatus] | None = None,
+        kinds: list[WorkflowKind] | None = None,
+        additional_metadata: list[str] | None = None,
+        order_by_field: WorkflowRunOrderByField | None = None,
+        order_by_direction: WorkflowRunOrderByDirection | None = None,
+    ) -> WorkflowRunList:
+        return await self.workflow_api.workflow_run_list(
+            tenant=self.tenant_id,
+            offset=offset,
+            limit=limit,
+            workflow_id=workflow_id,
+            event_id=event_id,
+            parent_workflow_run_id=parent_workflow_run_id,
+            parent_step_run_id=parent_step_run_id,
+            statuses=statuses,
+            kinds=kinds,
+            additional_metadata=additional_metadata,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+        )
+
+    async def workflow_run_get(self, workflow_run_id: str) -> WorkflowRun:
+        return await self.workflow_api.workflow_run_get(
+            tenant=self.tenant_id,
+            workflow_run=workflow_run_id,
+        )
+
+    async def workflow_run_replay(
+        self, workflow_run_ids: list[str]
+    ) -> ReplayWorkflowRunsResponse:
+        return await self.workflow_run_api.workflow_run_update_replay(
+            tenant=self.tenant_id,
+            replay_workflow_runs_request=ReplayWorkflowRunsRequest(
+                workflow_run_ids=workflow_run_ids,
+            ),
+        )
+
+    async def workflow_run_cancel(
+        self, workflow_run_id: str
+    ) -> WorkflowRunCancel200Response:
+        return await self.workflow_run_api.workflow_run_cancel(
+            tenant=self.tenant_id,
+            workflow_runs_cancel_request=WorkflowRunsCancelRequest(
+                workflowRunIds=[workflow_run_id],
+            ),
+        )
+
+    async def workflow_run_bulk_cancel(
+        self, workflow_run_ids: list[str]
+    ) -> WorkflowRunCancel200Response:
+        return await self.workflow_run_api.workflow_run_cancel(
+            tenant=self.tenant_id,
+            workflow_runs_cancel_request=WorkflowRunsCancelRequest(
+                workflowRunIds=workflow_run_ids,
+            ),
+        )
+
+    async def workflow_run_create(
+        self,
+        workflow_id: str,
+        input: dict[str, Any],
+        version: str | None = None,
+        additional_metadata: list[str] | None = None,
+    ) -> WorkflowRun:
+        return await self.workflow_run_api.workflow_run_create(
+            workflow=workflow_id,
+            version=version,
+            trigger_workflow_run_request=TriggerWorkflowRunRequest(
+                input=input,
+                additional_metadata=additional_metadata,
+            ),
+        )
+
+    async def cron_create(
+        self,
+        workflow_name: str,
+        cron_name: str,
+        expression: str,
+        input: dict[str, Any],
+        additional_metadata: dict[str, str],
+    ):
+        return await self.workflow_run_api.cron_workflow_trigger_create(
+            tenant=self.tenant_id,
+            workflow=workflow_name,
+            create_cron_workflow_trigger_request=CreateCronWorkflowTriggerRequest(
+                cronName=cron_name,
+                cronExpression=expression,
+                input=input,
+                additional_metadata=additional_metadata,
+            ),
+        )
+
+    async def cron_delete(self, cron_trigger_id: str):
+        return await self.workflow_api.workflow_cron_delete(
+            tenant=self.tenant_id,
+            cron_workflow=cron_trigger_id,
+        )
+
+    async def cron_list(
+        self,
+        offset: StrictInt | None = None,
+        limit: StrictInt | None = None,
+        workflow_id: str | None = None,
+        additional_metadata: list[str] | None = None,
+        order_by_field: CronWorkflowsOrderByField | None = None,
+        order_by_direction: WorkflowRunOrderByDirection | None = None,
+    ):
+        return await self.workflow_api.cron_workflow_list(
+            tenant=self.tenant_id,
+            offset=offset,
+            limit=limit,
+            workflow_id=workflow_id,
+            additional_metadata=additional_metadata,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+        )
+
+    async def cron_get(self, cron_trigger_id: str):
+        return await self.workflow_api.workflow_cron_get(
+            tenant=self.tenant_id,
+            cron_workflow=cron_trigger_id,
+        )
+
+    async def schedule_create(
+        self,
+        name: str,
+        trigger_at: datetime.datetime,
+        input: dict[str, Any],
+        additional_metadata: dict[str, str],
+    ):
+        return await self.workflow_run_api.scheduled_workflow_run_create(
+            tenant=self.tenant_id,
+            workflow=name,
+            schedule_workflow_run_request=ScheduleWorkflowRunRequest(
+                triggerAt=trigger_at,
+                input=input,
+                additional_metadata=additional_metadata,
+            ),
+        )
+
+    async def schedule_delete(self, scheduled_trigger_id: str):
+        return await self.workflow_api.workflow_scheduled_delete(
+            tenant=self.tenant_id,
+            scheduled_workflow_run=scheduled_trigger_id,
+        )
+
+    async def schedule_list(
+        self,
+        offset: StrictInt | None = None,
+        limit: StrictInt | None = None,
+        workflow_id: str | None = None,
+        additional_metadata: list[str] | None = None,
+        parent_workflow_run_id: str | None = None,
+        parent_step_run_id: str | None = None,
+        order_by_field: ScheduledWorkflowsOrderByField | None = None,
+        order_by_direction: WorkflowRunOrderByDirection | None = None,
+    ):
+        return await self.workflow_api.workflow_scheduled_list(
+            tenant=self.tenant_id,
+            offset=offset,
+            limit=limit,
+            workflow_id=workflow_id,
+            parent_workflow_run_id=parent_workflow_run_id,
+            parent_step_run_id=parent_step_run_id,
+            additional_metadata=additional_metadata,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+        )
+
+    async def schedule_get(self, scheduled_trigger_id: str):
+        return await self.workflow_api.workflow_scheduled_get(
+            tenant=self.tenant_id,
+            scheduled_workflow_run=scheduled_trigger_id,
+        )
+
+    async def list_logs(
+        self,
+        step_run_id: str,
+        offset: int | None = None,
+        limit: int | None = None,
+        levels: list[LogLineLevel] | None = None,
+        search: str | None = None,
+        order_by_field: LogLineOrderByField | None = None,
+        order_by_direction: LogLineOrderByDirection | None = None,
+    ) -> LogLineList:
+        return await self.log_api.log_line_list(
+            step_run=step_run_id,
+            offset=offset,
+            limit=limit,
+            levels=levels,
+            search=search,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+        )
+
+    async def events_list(
+        self,
+        offset: int | None = None,
+        limit: int | None = None,
+        keys: list[str] | None = None,
+        workflows: list[str] | None = None,
+        statuses: list[WorkflowRunStatus] | None = None,
+        search: str | None = None,
+        order_by_field: EventOrderByField | None = None,
+        order_by_direction: EventOrderByDirection | None = None,
+        additional_metadata: list[str] | None = None,
+    ) -> EventList:
+        return await self.event_api.event_list(
+            tenant=self.tenant_id,
+            offset=offset,
+            limit=limit,
+            keys=keys,
+            workflows=workflows,
+            statuses=statuses,
+            search=search,
+            order_by_field=order_by_field,
+            order_by_direction=order_by_direction,
+            additional_metadata=additional_metadata,
+        )
+
+    async def events_replay(self, event_ids: list[str] | EventList) -> EventList:
+        if isinstance(event_ids, EventList):
+            event_ids = [r.metadata.id for r in event_ids.rows]
+
+        return self.event_api.event_update_replay(
+            tenant=self.tenant_id,
+            replay_event_request=ReplayEventRequest(eventIds=event_ids),
+        )
+
+
+class RestApi:
+    def __init__(self, host: str, api_key: str, tenant_id: str):
+        self._loop = asyncio.new_event_loop()
+        self._thread = threading.Thread(target=self._run_event_loop, daemon=True)
+        self._thread.start()
+
+        # Initialize AsyncRestApi inside the event loop to ensure an active loop
+        self.aio = AsyncRestApi(host, api_key, tenant_id)
+
+        # Register the cleanup method to be called on exit
+        atexit.register(self._cleanup)
+
+    def _cleanup(self):
+        """
+        Stop the running thread and clean up the event loop.
+        """
+        self._run_coroutine(self.aio.close())
+        self._loop.call_soon_threadsafe(self._loop.stop)
+        self._thread.join()
+
+    def _run_event_loop(self):
+        """
+        Run the asyncio event loop in a separate thread.
+        """
+        asyncio.set_event_loop(self._loop)
+        self._loop.run_forever()
+
+    def _run_coroutine(self, coro) -> Any:
+        """
+        Execute a coroutine in the event loop and return the result.
+        """
+        future = asyncio.run_coroutine_threadsafe(coro, self._loop)
+        return future.result()
+
+    def workflow_list(self) -> WorkflowList:
+        return self._run_coroutine(self.aio.workflow_list())
+
+    def workflow_get(self, workflow_id: str) -> Workflow:
+        return self._run_coroutine(self.aio.workflow_get(workflow_id))
+
+    def workflow_version_get(
+        self, workflow_id: str, version: str | None = None
+    ) -> WorkflowVersion:
+        return self._run_coroutine(self.aio.workflow_version_get(workflow_id, version))
+
+    def workflow_run_list(
+        self,
+        workflow_id: str | None = None,
+        offset: int | None = None,
+        limit: int | None = None,
+        event_id: str | None = None,
+        parent_workflow_run_id: str | None = None,
+        parent_step_run_id: str | None = None,
+        statuses: list[WorkflowRunStatus] | None = None,
+        kinds: list[WorkflowKind] | None = None,
+        additional_metadata: list[str] | None = None,
+        order_by_field: WorkflowRunOrderByField | None = None,
+        order_by_direction: WorkflowRunOrderByDirection | None = None,
+    ) -> WorkflowRunList:
+        return self._run_coroutine(
+            self.aio.workflow_run_list(
+                workflow_id=workflow_id,
+                offset=offset,
+                limit=limit,
+                event_id=event_id,
+                parent_workflow_run_id=parent_workflow_run_id,
+                parent_step_run_id=parent_step_run_id,
+                statuses=statuses,
+                kinds=kinds,
+                additional_metadata=additional_metadata,
+                order_by_field=order_by_field,
+                order_by_direction=order_by_direction,
+            )
+        )
+
+    def workflow_run_get(self, workflow_run_id: str) -> WorkflowRun:
+        return self._run_coroutine(self.aio.workflow_run_get(workflow_run_id))
+
+    def workflow_run_cancel(self, workflow_run_id: str) -> WorkflowRunCancel200Response:
+        return self._run_coroutine(self.aio.workflow_run_cancel(workflow_run_id))
+
+    def workflow_run_bulk_cancel(
+        self, workflow_run_ids: list[str]
+    ) -> WorkflowRunCancel200Response:
+        return self._run_coroutine(self.aio.workflow_run_bulk_cancel(workflow_run_ids))
+
+    def workflow_run_create(
+        self,
+        workflow_id: str,
+        input: dict[str, Any],
+        version: str | None = None,
+        additional_metadata: list[str] | None = None,
+    ) -> WorkflowRun:
+        return self._run_coroutine(
+            self.aio.workflow_run_create(
+                workflow_id, input, version, additional_metadata
+            )
+        )
+
+    def cron_create(
+        self,
+        workflow_name: str,
+        cron_name: str,
+        expression: str,
+        input: dict[str, Any],
+        additional_metadata: dict[str, str],
+    ) -> CronWorkflows:
+        return self._run_coroutine(
+            self.aio.cron_create(
+                workflow_name, cron_name, expression, input, additional_metadata
+            )
+        )
+
+    def cron_delete(self, cron_trigger_id: str):
+        return self._run_coroutine(self.aio.cron_delete(cron_trigger_id))
+
+    def cron_list(
+        self,
+        offset: int | None = None,
+        limit: int | None = None,
+        workflow_id: str | None = None,
+        additional_metadata: list[str] | None = None,
+        order_by_field: CronWorkflowsOrderByField | None = None,
+        order_by_direction: WorkflowRunOrderByDirection | None = None,
+    ):
+        return self._run_coroutine(
+            self.aio.cron_list(
+                offset,
+                limit,
+                workflow_id,
+                additional_metadata,
+                order_by_field,
+                order_by_direction,
+            )
+        )
+
+    def cron_get(self, cron_trigger_id: str):
+        return self._run_coroutine(self.aio.cron_get(cron_trigger_id))
+
+    def schedule_create(
+        self,
+        workflow_name: str,
+        trigger_at: datetime.datetime,
+        input: dict[str, Any],
+        additional_metadata: dict[str, str],
+    ):
+        return self._run_coroutine(
+            self.aio.schedule_create(
+                workflow_name, trigger_at, input, additional_metadata
+            )
+        )
+
+    def schedule_delete(self, scheduled_trigger_id: str):
+        return self._run_coroutine(self.aio.schedule_delete(scheduled_trigger_id))
+
+    def schedule_list(
+        self,
+        offset: int | None = None,
+        limit: int | None = None,
+        workflow_id: str | None = None,
+        additional_metadata: list[str] | None = None,
+        order_by_field: CronWorkflowsOrderByField | None = None,
+        order_by_direction: WorkflowRunOrderByDirection | None = None,
+    ):
+        return self._run_coroutine(
+            self.aio.schedule_list(
+                offset,
+                limit,
+                workflow_id,
+                additional_metadata,
+                order_by_field,
+                order_by_direction,
+            )
+        )
+
+    def schedule_get(self, scheduled_trigger_id: str):
+        return self._run_coroutine(self.aio.schedule_get(scheduled_trigger_id))
+
+    def list_logs(
+        self,
+        step_run_id: str,
+        offset: int | None = None,
+        limit: int | None = None,
+        levels: list[LogLineLevel] | None = None,
+        search: str | None = None,
+        order_by_field: LogLineOrderByField | None = None,
+        order_by_direction: LogLineOrderByDirection | None = None,
+    ) -> LogLineList:
+        return self._run_coroutine(
+            self.aio.list_logs(
+                step_run_id=step_run_id,
+                offset=offset,
+                limit=limit,
+                levels=levels,
+                search=search,
+                order_by_field=order_by_field,
+                order_by_direction=order_by_direction,
+            )
+        )
+
+    def events_list(
+        self,
+        offset: int | None = None,
+        limit: int | None = None,
+        keys: list[str] | None = None,
+        workflows: list[str] | None = None,
+        statuses: list[WorkflowRunStatus] | None = None,
+        search: str | None = None,
+        order_by_field: EventOrderByField | None = None,
+        order_by_direction: EventOrderByDirection | None = None,
+        additional_metadata: list[str] | None = None,
+    ) -> EventList:
+        return self._run_coroutine(
+            self.aio.events_list(
+                offset=offset,
+                limit=limit,
+                keys=keys,
+                workflows=workflows,
+                statuses=statuses,
+                search=search,
+                order_by_field=order_by_field,
+                order_by_direction=order_by_direction,
+                additional_metadata=additional_metadata,
+            )
+        )
+
+    def events_replay(self, event_ids: list[str] | EventList) -> EventList:
+        return self._run_coroutine(self.aio.events_replay(event_ids))
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/run_event_listener.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/run_event_listener.py
new file mode 100644
index 00000000..b5db6a74
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/run_event_listener.py
@@ -0,0 +1,260 @@
+import asyncio
+import json
+from typing import AsyncGenerator
+
+import grpc
+
+from hatchet_sdk.connection import new_conn
+from hatchet_sdk.contracts.dispatcher_pb2 import (
+    RESOURCE_TYPE_STEP_RUN,
+    RESOURCE_TYPE_WORKFLOW_RUN,
+    ResourceEventType,
+    SubscribeToWorkflowEventsRequest,
+    WorkflowEvent,
+)
+from hatchet_sdk.contracts.dispatcher_pb2_grpc import DispatcherStub
+
+from ..loader import ClientConfig
+from ..metadata import get_metadata
+
+DEFAULT_ACTION_LISTENER_RETRY_INTERVAL = 5  # seconds
+DEFAULT_ACTION_LISTENER_RETRY_COUNT = 5
+
+
+class StepRunEventType:
+    STEP_RUN_EVENT_TYPE_STARTED = "STEP_RUN_EVENT_TYPE_STARTED"
+    STEP_RUN_EVENT_TYPE_COMPLETED = "STEP_RUN_EVENT_TYPE_COMPLETED"
+    STEP_RUN_EVENT_TYPE_FAILED = "STEP_RUN_EVENT_TYPE_FAILED"
+    STEP_RUN_EVENT_TYPE_CANCELLED = "STEP_RUN_EVENT_TYPE_CANCELLED"
+    STEP_RUN_EVENT_TYPE_TIMED_OUT = "STEP_RUN_EVENT_TYPE_TIMED_OUT"
+    STEP_RUN_EVENT_TYPE_STREAM = "STEP_RUN_EVENT_TYPE_STREAM"
+
+
+class WorkflowRunEventType:
+    WORKFLOW_RUN_EVENT_TYPE_STARTED = "WORKFLOW_RUN_EVENT_TYPE_STARTED"
+    WORKFLOW_RUN_EVENT_TYPE_COMPLETED = "WORKFLOW_RUN_EVENT_TYPE_COMPLETED"
+    WORKFLOW_RUN_EVENT_TYPE_FAILED = "WORKFLOW_RUN_EVENT_TYPE_FAILED"
+    WORKFLOW_RUN_EVENT_TYPE_CANCELLED = "WORKFLOW_RUN_EVENT_TYPE_CANCELLED"
+    WORKFLOW_RUN_EVENT_TYPE_TIMED_OUT = "WORKFLOW_RUN_EVENT_TYPE_TIMED_OUT"
+
+
+step_run_event_type_mapping = {
+    ResourceEventType.RESOURCE_EVENT_TYPE_STARTED: StepRunEventType.STEP_RUN_EVENT_TYPE_STARTED,
+    ResourceEventType.RESOURCE_EVENT_TYPE_COMPLETED: StepRunEventType.STEP_RUN_EVENT_TYPE_COMPLETED,
+    ResourceEventType.RESOURCE_EVENT_TYPE_FAILED: StepRunEventType.STEP_RUN_EVENT_TYPE_FAILED,
+    ResourceEventType.RESOURCE_EVENT_TYPE_CANCELLED: StepRunEventType.STEP_RUN_EVENT_TYPE_CANCELLED,
+    ResourceEventType.RESOURCE_EVENT_TYPE_TIMED_OUT: StepRunEventType.STEP_RUN_EVENT_TYPE_TIMED_OUT,
+    ResourceEventType.RESOURCE_EVENT_TYPE_STREAM: StepRunEventType.STEP_RUN_EVENT_TYPE_STREAM,
+}
+
+workflow_run_event_type_mapping = {
+    ResourceEventType.RESOURCE_EVENT_TYPE_STARTED: WorkflowRunEventType.WORKFLOW_RUN_EVENT_TYPE_STARTED,
+    ResourceEventType.RESOURCE_EVENT_TYPE_COMPLETED: WorkflowRunEventType.WORKFLOW_RUN_EVENT_TYPE_COMPLETED,
+    ResourceEventType.RESOURCE_EVENT_TYPE_FAILED: WorkflowRunEventType.WORKFLOW_RUN_EVENT_TYPE_FAILED,
+    ResourceEventType.RESOURCE_EVENT_TYPE_CANCELLED: WorkflowRunEventType.WORKFLOW_RUN_EVENT_TYPE_CANCELLED,
+    ResourceEventType.RESOURCE_EVENT_TYPE_TIMED_OUT: WorkflowRunEventType.WORKFLOW_RUN_EVENT_TYPE_TIMED_OUT,
+}
+
+
+class StepRunEvent:
+    def __init__(self, type: StepRunEventType, payload: str):
+        self.type = type
+        self.payload = payload
+
+
+def new_listener(config: ClientConfig):
+    return RunEventListenerClient(config=config)
+
+
+class RunEventListener:
+
+    workflow_run_id: str = None
+    additional_meta_kv: tuple[str, str] = None
+
+    def __init__(self, client: DispatcherStub, token: str):
+        self.client = client
+        self.stop_signal = False
+        self.token = token
+
+    @classmethod
+    def for_run_id(cls, workflow_run_id: str, client: DispatcherStub, token: str):
+        listener = RunEventListener(client, token)
+        listener.workflow_run_id = workflow_run_id
+        return listener
+
+    @classmethod
+    def for_additional_meta(
+        cls, key: str, value: str, client: DispatcherStub, token: str
+    ):
+        listener = RunEventListener(client, token)
+        listener.additional_meta_kv = (key, value)
+        return listener
+
+    def abort(self):
+        self.stop_signal = True
+
+    def __aiter__(self):
+        return self._generator()
+
+    async def __anext__(self):
+        return await self._generator().__anext__()
+
+    def __iter__(self):
+        try:
+            loop = asyncio.get_event_loop()
+        except RuntimeError as e:
+            if str(e).startswith("There is no current event loop in thread"):
+                loop = asyncio.new_event_loop()
+                asyncio.set_event_loop(loop)
+            else:
+                raise e
+
+        async_iter = self.__aiter__()
+
+        while True:
+            try:
+                future = asyncio.ensure_future(async_iter.__anext__())
+                yield loop.run_until_complete(future)
+            except StopAsyncIteration:
+                break
+            except Exception as e:
+                print(f"Error in synchronous iterator: {e}")
+                break
+
+    async def _generator(self) -> AsyncGenerator[StepRunEvent, None]:
+        while True:
+            if self.stop_signal:
+                listener = None
+                break
+
+            listener = await self.retry_subscribe()
+
+            try:
+                async for workflow_event in listener:
+                    eventType = None
+                    if workflow_event.resourceType == RESOURCE_TYPE_STEP_RUN:
+                        if workflow_event.eventType in step_run_event_type_mapping:
+                            eventType = step_run_event_type_mapping[
+                                workflow_event.eventType
+                            ]
+                        else:
+                            raise Exception(
+                                f"Unknown event type: {workflow_event.eventType}"
+                            )
+                        payload = None
+
+                        try:
+                            if workflow_event.eventPayload:
+                                payload = json.loads(workflow_event.eventPayload)
+                        except Exception as e:
+                            payload = workflow_event.eventPayload
+                            pass
+
+                        yield StepRunEvent(type=eventType, payload=payload)
+                    elif workflow_event.resourceType == RESOURCE_TYPE_WORKFLOW_RUN:
+                        if workflow_event.eventType in workflow_run_event_type_mapping:
+                            eventType = workflow_run_event_type_mapping[
+                                workflow_event.eventType
+                            ]
+                        else:
+                            raise Exception(
+                                f"Unknown event type: {workflow_event.eventType}"
+                            )
+
+                        payload = None
+
+                        try:
+                            if workflow_event.eventPayload:
+                                payload = json.loads(workflow_event.eventPayload)
+                        except Exception as e:
+                            pass
+
+                        yield StepRunEvent(type=eventType, payload=payload)
+
+                    if workflow_event.hangup:
+                        listener = None
+                        break
+
+                break
+            except grpc.RpcError as e:
+                # Handle different types of errors
+                if e.code() == grpc.StatusCode.CANCELLED:
+                    # Context cancelled, unsubscribe and close
+                    break
+                elif e.code() == grpc.StatusCode.UNAVAILABLE:
+                    # Retry logic
+                    # logger.info("Could not connect to Hatchet, retrying...")
+                    listener = await self.retry_subscribe()
+                elif e.code() == grpc.StatusCode.DEADLINE_EXCEEDED:
+                    # logger.info("Deadline exceeded, retrying subscription")
+                    continue
+                else:
+                    # Unknown error, report and break
+                    # logger.error(f"Failed to receive message: {e}")
+                    break
+                # Raise StopAsyncIteration to properly end the generator
+
+    async def retry_subscribe(self):
+        retries = 0
+
+        while retries < DEFAULT_ACTION_LISTENER_RETRY_COUNT:
+            try:
+                if retries > 0:
+                    await asyncio.sleep(DEFAULT_ACTION_LISTENER_RETRY_INTERVAL)
+
+                if self.workflow_run_id is not None:
+                    return self.client.SubscribeToWorkflowEvents(
+                        SubscribeToWorkflowEventsRequest(
+                            workflowRunId=self.workflow_run_id,
+                        ),
+                        metadata=get_metadata(self.token),
+                    )
+                elif self.additional_meta_kv is not None:
+                    return self.client.SubscribeToWorkflowEvents(
+                        SubscribeToWorkflowEventsRequest(
+                            additionalMetaKey=self.additional_meta_kv[0],
+                            additionalMetaValue=self.additional_meta_kv[1],
+                        ),
+                        metadata=get_metadata(self.token),
+                    )
+                else:
+                    raise Exception("no listener method provided")
+
+            except grpc.RpcError as e:
+                if e.code() == grpc.StatusCode.UNAVAILABLE:
+                    retries = retries + 1
+                else:
+                    raise ValueError(f"gRPC error: {e}")
+
+
+class RunEventListenerClient:
+    def __init__(self, config: ClientConfig):
+        self.token = config.token
+        self.config = config
+        self.client: DispatcherStub = None
+
+    def stream_by_run_id(self, workflow_run_id: str):
+        return self.stream(workflow_run_id)
+
+    def stream(self, workflow_run_id: str):
+        if not isinstance(workflow_run_id, str) and hasattr(workflow_run_id, "__str__"):
+            workflow_run_id = str(workflow_run_id)
+
+        if not self.client:
+            aio_conn = new_conn(self.config, True)
+            self.client = DispatcherStub(aio_conn)
+
+        return RunEventListener.for_run_id(workflow_run_id, self.client, self.token)
+
+    def stream_by_additional_metadata(self, key: str, value: str):
+        if not self.client:
+            aio_conn = new_conn(self.config, True)
+            self.client = DispatcherStub(aio_conn)
+
+        return RunEventListener.for_additional_meta(key, value, self.client, self.token)
+
+    async def on(self, workflow_run_id: str, handler: callable = None):
+        async for event in self.stream(workflow_run_id):
+            # call the handler if provided
+            if handler:
+                handler(event)
diff --git a/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/workflow_listener.py b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/workflow_listener.py
new file mode 100644
index 00000000..8bf71a3c
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/hatchet_sdk/clients/workflow_listener.py
@@ -0,0 +1,277 @@
+import asyncio
+import json
+from collections.abc import AsyncIterator
+from typing import AsyncGenerator
+
+import grpc
+from grpc._cython import cygrpc
+
+from hatchet_sdk.clients.event_ts import Event_ts, read_with_interrupt
+from hatchet_sdk.connection import new_conn
+from hatchet_sdk.contracts.dispatcher_pb2 import (
+    SubscribeToWorkflowRunsRequest,
+    WorkflowRunEvent,
+)
+from hatchet_sdk.contracts.dispatcher_pb2_grpc import DispatcherStub
+
+from ..loader import ClientConfig
+from ..logger import logger
+from ..metadata import get_metadata
+
+DEFAULT_WORKFLOW_LISTENER_RETRY_INTERVAL = 3  # seconds
+DEFAULT_WORKFLOW_LISTENER_RETRY_COUNT = 5
+DEFAULT_WORKFLOW_LISTENER_INTERRUPT_INTERVAL = 1800  # 30 minutes
+
+DEDUPE_MESSAGE = "DUPLICATE_WORKFLOW_RUN"
+
+
+class _Subscription:
+    def __init__(self, id: int, workflow_run_id: str):
+        self.id = id
+        self.workflow_run_id = workflow_run_id
+        self.queue: asyncio.Queue[WorkflowRunEvent | None] = asyncio.Queue()
+
+    async def __aiter__(self):
+        return self
+
+    async def __anext__(self) -> WorkflowRunEvent:
+        return await self.queue.get()
+
+    async def get(self) -> WorkflowRunEvent:
+        event = await self.queue.get()
+
+        if event is None:
+            raise StopAsyncIteration
+
+        return event
+
+    async def put(self, item: WorkflowRunEvent):
+        await self.queue.put(item)
+
+    async def close(self):
+        await self.queue.put(None)
+
+
+class PooledWorkflowRunListener:
+    # list of all active subscriptions, mapping from a subscription id to a workflow run id
+    subscriptionsToWorkflows: dict[int, str] = {}
+
+    # list of workflow run ids mapped to an array of subscription ids
+    workflowsToSubscriptions: dict[str, list[int]] = {}
+
+    subscription_counter: int = 0
+    subscription_counter_lock: asyncio.Lock = asyncio.Lock()
+
+    requests: asyncio.Queue[SubscribeToWorkflowRunsRequest] = asyncio.Queue()
+
+    listener: AsyncGenerator[WorkflowRunEvent, None] = None
+    listener_task: asyncio.Task = None
+
+    curr_requester: int = 0
+
+    # events have keys of the format workflow_run_id + subscription_id
+    events: dict[int, _Subscription] = {}
+
+    interrupter: asyncio.Task = None
+
+    def __init__(self, config: ClientConfig):
+        try:
+            asyncio.get_running_loop()
+        except RuntimeError:
+            loop = asyncio.new_event_loop()
+            asyncio.set_event_loop(loop)
+
+        conn = new_conn(config, True)
+        self.client = DispatcherStub(conn)
+        self.token = config.token
+        self.config = config
+
+    async def _interrupter(self):
+        """
+        _interrupter runs in a separate thread and interrupts the listener according to a configurable duration.
+        """
+        await asyncio.sleep(DEFAULT_WORKFLOW_LISTENER_INTERRUPT_INTERVAL)
+
+        if self.interrupt is not None:
+            self.interrupt.set()
+
+    async def _init_producer(self):
+        try:
+            if not self.listener:
+                while True:
+                    try:
+                        self.listener = await self._retry_subscribe()
+
+                        logger.debug("Workflow run listener connected.")
+
+                        # spawn an interrupter task
+                        if self.interrupter is not None and not self.interrupter.done():
+                            self.interrupter.cancel()
+
+                        self.interrupter = asyncio.create_task(self._interrupter())
+
+                        while True:
+                            self.interrupt = Event_ts()
+                            t = asyncio.create_task(
+                                read_with_interrupt(self.listener, self.interrupt)
+                            )
+                            await self.interrupt.wait()
+
+                            if not t.done():
+                                # print a warning
+                                logger.warning(
+                                    "Interrupted read_with_interrupt task of workflow run listener"
+                                )
+
+                                t.cancel()
+                                self.listener.cancel()
+                                await asyncio.sleep(
+                                    DEFAULT_WORKFLOW_LISTENER_RETRY_INTERVAL
+                                )
+                                break
+
+                            workflow_event: WorkflowRunEvent = t.result()
+
+                            if workflow_event is cygrpc.EOF:
+                                break
+
+                            # get a list of subscriptions for this workflow
+                            subscriptions = self.workflowsToSubscriptions.get(
+                                workflow_event.workflowRunId, []
+                            )
+
+                            for subscription_id in subscriptions:
+                                await self.events[subscription_id].put(workflow_event)
+
+                    except grpc.RpcError as e:
+                        logger.debug(f"grpc error in workflow run listener: {e}")
+                        await asyncio.sleep(DEFAULT_WORKFLOW_LISTENER_RETRY_INTERVAL)
+                        continue
+
+        except Exception as e:
+            logger.error(f"Error in workflow run listener: {e}")
+
+            self.listener = None
+
+            # close all subscriptions
+            for subscription_id in self.events:
+                await self.events[subscription_id].close()
+
+            raise e
+
+    async def _request(self) -> AsyncIterator[SubscribeToWorkflowRunsRequest]:
+        self.curr_requester = self.curr_requester + 1
+
+        # replay all existing subscriptions
+        workflow_run_set = set(self.subscriptionsToWorkflows.values())
+
+        for workflow_run_id in workflow_run_set:
+            yield SubscribeToWorkflowRunsRequest(
+                workflowRunId=workflow_run_id,
+            )
+
+        while True:
+            request = await self.requests.get()
+
+            # if the request is an int which matches the current requester, then we should stop
+            if request == self.curr_requester:
+                break
+
+            # if we've gotten an int that doesn't match the current requester, then we should ignore it
+            if isinstance(request, int):
+                continue
+
+            yield request
+            self.requests.task_done()
+
+    def cleanup_subscription(self, subscription_id: int):
+        workflow_run_id = self.subscriptionsToWorkflows[subscription_id]
+
+        if workflow_run_id in self.workflowsToSubscriptions:
+            self.workflowsToSubscriptions[workflow_run_id].remove(subscription_id)
+
+        del self.subscriptionsToWorkflows[subscription_id]
+        del self.events[subscription_id]
+
+    async def subscribe(self, workflow_run_id: str):
+        init_producer: asyncio.Task = None
+        try:
+            # create a new subscription id, place a mutex on the counter
+            await self.subscription_counter_lock.acquire()
+            self.subscription_counter += 1
+            subscription_id = self.subscription_counter
+            self.subscription_counter_lock.release()
+
+            self.subscriptionsToWorkflows[subscription_id] = workflow_run_id
+
+            if workflow_run_id not in self.workflowsToSubscriptions:
+                self.workflowsToSubscriptions[workflow_run_id] = [subscription_id]
+            else:
+                self.workflowsToSubscriptions[workflow_run_id].append(subscription_id)
+
+            self.events[subscription_id] = _Subscription(
+                subscription_id, workflow_run_id
+            )
+
+            await self.requests.put(
+                SubscribeToWorkflowRunsRequest(
+                    workflowRunId=workflow_run_id,
+                )
+            )
+
+            if not self.listener_task or self.listener_task.done():
+                self.listener_task = asyncio.create_task(self._init_producer())
+
+            event = await self.events[subscription_id].get()
+
+            return event
+        except asyncio.CancelledError:
+            raise
+        finally:
+            self.cleanup_subscription(subscription_id)
+
+    async def result(self, workflow_run_id: str):
+        from hatchet_sdk.clients.admin import DedupeViolationErr
+
+        event = await self.subscribe(workflow_run_id)
+
+        errors = []
+
+        if event.results:
+            errors = [result.error for result in event.results if result.error]
+
+        if errors:
+            if DEDUPE_MESSAGE in errors[0]:
+                raise DedupeViolationErr(errors[0])
+            else:
+                raise Exception(f"Workflow Errors: {errors}")
+
+        results = {
+            result.stepReadableId: json.loads(result.output)
+            for result in event.results
+            if result.output
+        }
+
+        return results
+
+    async def _retry_subscribe(self):
+        retries = 0
+
+        while retries < DEFAULT_WORKFLOW_LISTENER_RETRY_COUNT:
+            try:
+                if retries > 0:
+                    await asyncio.sleep(DEFAULT_WORKFLOW_LISTENER_RETRY_INTERVAL)
+
+                # signal previous async iterator to stop
+                if self.curr_requester != 0:
+                    self.requests.put_nowait(self.curr_requester)
+
+                return self.client.SubscribeToWorkflowRuns(
+                    self._request(),
+                    metadata=get_metadata(self.token),
+                )
+            except grpc.RpcError as e:
+                if e.code() == grpc.StatusCode.UNAVAILABLE:
+                    retries = retries + 1
+                else:
+                    raise ValueError(f"gRPC error: {e}")