From 73fc189aadba09c5be3ac399753fc3b1a476b7ea Mon Sep 17 00:00:00 2001 From: Chad Retz Date: Tue, 14 Jul 2026 09:44:08 -0500 Subject: [PATCH 1/2] Update API specs and bump version to 0.9.1 --- baseten/client/managementapi/__init__.py | 192 +- baseten/client/managementapi/_client.py | 1357 ++- baseten/client/managementapi/_models.py | 2679 ++++- baseten/client/modelconfig/__init__.py | 2 + baseten/client/modelconfig/_models.py | 30 +- pyproject.toml | 2 +- scripts/apigen/postprocess.py | 4 +- scripts/apigen/specs/config.schema.json | 68 +- scripts/apigen/specs/inference.json | 11 +- scripts/apigen/specs/management.json | 12636 +++++++++++++-------- tests/client/test_management.py | 1 + uv.lock | 2 +- 12 files changed, 11515 insertions(+), 5469 deletions(-) diff --git a/baseten/client/managementapi/__init__.py b/baseten/client/managementapi/__init__.py index 499f059..b11f82a 100644 --- a/baseten/client/managementapi/__init__.py +++ b/baseten/client/managementapi/__init__.py @@ -15,10 +15,12 @@ APIKey, APIKeyCategory, APIKeyInfo, + APIKeyOwner, APIKeyTombstone, APIKeys, AWSCredentials, ActivateResponse, + ActiveJobAtSubmit, AuthCode, AutoscalingSettings, AwsIamDockerAuth, @@ -28,6 +30,7 @@ BillableResource, CancelPromotionResponse, CancelPromotionStatus, + CapacityAtSubmit, Chain, ChainDeployment, ChainDeploymentTombstone, @@ -42,14 +45,20 @@ ChainletEnvironmentSettingsRequest, Chains, CheckpointFile, - CheckpointSearchRequest, - CheckpointSearchResponse, CheckpointSyncStatus, Checkpoints, + Component, + ComputeCost, + ComputeCost1, + CostPerMillionInputTokens, + CostPerMillionOutputTokens, CreateAPIKeyRequest, CreateApiKeyForGroupRequest, CreateApiKeyForGroupResponse, CreateChainEnvironmentRequest, + CreateDeploymentPatchRequest, + CreateDeploymentPatchResponse, + CreateEndpointRequest, CreateEnvironmentRequest, CreateGroupRequest, CreateJobWeightConfig, @@ -61,17 +70,10 @@ CreateLoopsRunResponse, CreateLoopsSamplerRequest, CreateLoopsSamplerResponse, - CreateLoopsSessionRequest, CreateLoopsSessionResponse, CreateModelDeploymentRequest, CreateModelRequest, CreateModelWeightSnapshotRequest, - CreateSamplingServerRequest, - CreateSamplingServerResponse, - CreateTrainerServerRequest, - CreateTrainerServerResponse, - CreateTrainerSessionRequest, - CreateTrainerSessionResponse, CreateTrainingJob, CreateTrainingJobAccelerator, CreateTrainingJobCacheConfig, @@ -96,9 +98,19 @@ DeploymentArchiveSource, DeploymentConfigOutputFormat, DeploymentConfigResponse, + DeploymentPatchAction, + DeploymentPatchOpConfig, + DeploymentPatchOpEnvVar, + DeploymentPatchOpExternalData, + DeploymentPatchOpModelCode, + DeploymentPatchOpPackage, + DeploymentPatchOpPythonRequirement, + DeploymentPatchPoint, + DeploymentPatchPointWithHash, DeploymentStatus, DeploymentTombstone, Deployments, + DeploymentsRequest, DockerAuth, DockerAuthType, DownloadDeploymentResponse, @@ -106,10 +118,20 @@ EffectiveModelConfig, EffectiveRateLimit, EffectiveUsageLimit, + Endpoint, + EndpointTarget, + EndpointTargetRequest, + EndpointTombstone, + EndpointsResponse, Environment, + EnvironmentGroup, + EnvironmentGroupManageAccess, + EnvironmentGroupUser, + EnvironmentGroups, Environments, FileSummary, GatewayKeyInfo, + GatewayProvider, GcpOidcDockerAuth, GcpServiceAccountJsonDockerAuth, GetAuthCodesResponse, @@ -117,6 +139,10 @@ GetCacheSummaryResponse, GetDeploymentConfigRequest, GetDeploymentLogsRequest, + GetDeploymentMetricsRequest, + GetDeploymentPatchesStateResponse, + GetEnvironmentLogsRequest, + GetEnvironmentMetricsRequest, GetLogsResponse, GetLoopsCapabilitiesResponse, GetLoopsDeploymentLogsRequest, @@ -126,8 +152,8 @@ GetLoopsRunResponse, GetLoopsSamplerResponse, GetLoopsSessionResponse, - GetTrainerServerCheckpointFilesResponse, - GetTrainerServerCheckpointsResponse, + GetLoopsUserConfigResponse, + GetModelMetricsResponse, GetTrainingGpuCapacityResponse, GetTrainingJobCheckpointFilesRequest, GetTrainingJobCheckpointFilesResponse, @@ -135,6 +161,7 @@ GetTrainingJobLogsRequest, GetTrainingJobMetricsRequest, GetTrainingJobMetricsResponse, + GetTrainingJobQueueContextResponse, GetTrainingJobResponse, GetTrainingProjectResponse, GitInfo, @@ -173,7 +200,9 @@ ListTrainingProjectsResponse, LoadCheckpointConfig, Log, + LogLevel, LoopsCheckpoint, + LoopsCheckpointConfig, LoopsCheckpointFilesResponse, LoopsDeployment, LoopsDeploymentMetrics, @@ -183,21 +212,39 @@ LoopsSampler, LoopsSamplerStatus, LoopsSession, + LoopsUserConfig, MaxScaleDownRate, Model, + ModelAPI, + ModelAPIOrgDetails, + ModelAPIsRequest, + ModelAPIsResponse, ModelApiItem, ModelApisUsage, ModelArchiveSource, ModelConfig, + ModelMetricDescriptor, + ModelMetricKind, + ModelMetricMode, + ModelMetricUnitHint, + ModelMetricValueSet, ModelTombstone, ModelWeightSnapshot, Models, + ModelsRequest, Name, Name1, + Name2, OrderBy, PaginationResponse, PatchInteractiveSessionRequest, PatchInteractiveSessionResponse, + PatchLoopsUserConfigRequest, + PatchLoopsUserConfigResponse, + PatchOps, + PatchTeamTrainingGpuCapacityRequest, + PatchTeamTrainingGpuCapacityResponse, + PendingJobAheadAtSubmit, PrepareModelUploadRequest, PrepareModelUploadResponse, PromoteRequest, @@ -205,23 +252,23 @@ PromoteToEnvironmentRequest, PromotionCleanupStrategy, PromotionSettings, + QueueEvent, RateLimit, RateLimitUnit, RecreateTrainingJobResponse, RegisterAPIKeyRequest, RegisterAPIKeyResponse, RegistrySecretDockerAuth, + Replica, + RequestId, ResourceKind, ResponseTimeDatapoint, RetryDeploymentResponse, RollingDeployConfig, RollingDeployStrategy, - SamplingServer, - SearchTrainersRequest, - SearchTrainersResponse, + SearchPattern, SearchTrainingJobsRequest, SearchTrainingJobsResponse, - SearchedTrainer, Secret, SecretReference, SecretTombstone, @@ -241,14 +288,19 @@ Subtotal7, Subtotal8, SupportedModel, + SurchargeCost, + SurchargeCost1, + SyncDeploymentPatchesRequest, + SyncDeploymentPatchesResponse, + Target, + Targets, Team, + TeamTrainingGpuCapacityItem, Teams, + TeamsRequest, TerminateReplicaResponse, Total, TrainerCheckpointTarget, - TrainerServer, - TrainerServerCheckpoint, - TrainerSession, TrainingGpuCapacityItem, TrainingItem, TrainingJob, @@ -270,6 +322,9 @@ UpdateChainletEnvironmentAutoscalingSettingsRequest, UpdateChainletEnvironmentInstanceTypeRequest, UpdateChainletEnvironmentInstanceTypeResponse, + UpdateEndpointRequest, + UpdateEnvironmentGroupManageAccess, + UpdateEnvironmentGroupRequest, UpdateEnvironmentRequest, UpdateGroupMetadata, UpdateGroupRequest, @@ -277,6 +332,8 @@ UpdateLibraryListingVersionRequest, UpdatePromotionSettings, UpdateRollingDeployConfig, + UpdateTrainingJobRequest, + UpdateTrainingJobResponse, UpsertSecretRequest, UpsertTrainingProject, UpsertTrainingProjectRequest, @@ -287,6 +344,9 @@ UsageSummaryRequest, User, UserInfo, + UsersRequest, + UsersResponse, + V1AvailabilityModel, V1InteractiveSessionAuthProvider, V1InteractiveSessionProvider, V1InteractiveSessionTrigger, @@ -301,10 +361,12 @@ "APIKey", "APIKeyCategory", "APIKeyInfo", + "APIKeyOwner", "APIKeyTombstone", "APIKeys", "AWSCredentials", "ActivateResponse", + "ActiveJobAtSubmit", "AuthCode", "AutoscalingSettings", "AwsIamDockerAuth", @@ -314,6 +376,7 @@ "BillableResource", "CancelPromotionResponse", "CancelPromotionStatus", + "CapacityAtSubmit", "Chain", "ChainDeployment", "ChainDeploymentTombstone", @@ -328,14 +391,20 @@ "ChainletEnvironmentSettingsRequest", "Chains", "CheckpointFile", - "CheckpointSearchRequest", - "CheckpointSearchResponse", "CheckpointSyncStatus", "Checkpoints", + "Component", + "ComputeCost", + "ComputeCost1", + "CostPerMillionInputTokens", + "CostPerMillionOutputTokens", "CreateAPIKeyRequest", "CreateApiKeyForGroupRequest", "CreateApiKeyForGroupResponse", "CreateChainEnvironmentRequest", + "CreateDeploymentPatchRequest", + "CreateDeploymentPatchResponse", + "CreateEndpointRequest", "CreateEnvironmentRequest", "CreateGroupRequest", "CreateJobWeightConfig", @@ -347,17 +416,10 @@ "CreateLoopsRunResponse", "CreateLoopsSamplerRequest", "CreateLoopsSamplerResponse", - "CreateLoopsSessionRequest", "CreateLoopsSessionResponse", "CreateModelDeploymentRequest", "CreateModelRequest", "CreateModelWeightSnapshotRequest", - "CreateSamplingServerRequest", - "CreateSamplingServerResponse", - "CreateTrainerServerRequest", - "CreateTrainerServerResponse", - "CreateTrainerSessionRequest", - "CreateTrainerSessionResponse", "CreateTrainingJob", "CreateTrainingJobAccelerator", "CreateTrainingJobCacheConfig", @@ -382,9 +444,19 @@ "DeploymentArchiveSource", "DeploymentConfigOutputFormat", "DeploymentConfigResponse", + "DeploymentPatchAction", + "DeploymentPatchOpConfig", + "DeploymentPatchOpEnvVar", + "DeploymentPatchOpExternalData", + "DeploymentPatchOpModelCode", + "DeploymentPatchOpPackage", + "DeploymentPatchOpPythonRequirement", + "DeploymentPatchPoint", + "DeploymentPatchPointWithHash", "DeploymentStatus", "DeploymentTombstone", "Deployments", + "DeploymentsRequest", "DockerAuth", "DockerAuthType", "DownloadDeploymentResponse", @@ -392,10 +464,20 @@ "EffectiveModelConfig", "EffectiveRateLimit", "EffectiveUsageLimit", + "Endpoint", + "EndpointTarget", + "EndpointTargetRequest", + "EndpointTombstone", + "EndpointsResponse", "Environment", + "EnvironmentGroup", + "EnvironmentGroupManageAccess", + "EnvironmentGroupUser", + "EnvironmentGroups", "Environments", "FileSummary", "GatewayKeyInfo", + "GatewayProvider", "GcpOidcDockerAuth", "GcpServiceAccountJsonDockerAuth", "GetAuthCodesResponse", @@ -403,6 +485,10 @@ "GetCacheSummaryResponse", "GetDeploymentConfigRequest", "GetDeploymentLogsRequest", + "GetDeploymentMetricsRequest", + "GetDeploymentPatchesStateResponse", + "GetEnvironmentLogsRequest", + "GetEnvironmentMetricsRequest", "GetLogsResponse", "GetLoopsCapabilitiesResponse", "GetLoopsDeploymentLogsRequest", @@ -412,8 +498,8 @@ "GetLoopsRunResponse", "GetLoopsSamplerResponse", "GetLoopsSessionResponse", - "GetTrainerServerCheckpointFilesResponse", - "GetTrainerServerCheckpointsResponse", + "GetLoopsUserConfigResponse", + "GetModelMetricsResponse", "GetTrainingGpuCapacityResponse", "GetTrainingJobCheckpointFilesRequest", "GetTrainingJobCheckpointFilesResponse", @@ -421,6 +507,7 @@ "GetTrainingJobLogsRequest", "GetTrainingJobMetricsRequest", "GetTrainingJobMetricsResponse", + "GetTrainingJobQueueContextResponse", "GetTrainingJobResponse", "GetTrainingProjectResponse", "GitInfo", @@ -459,7 +546,9 @@ "ListTrainingProjectsResponse", "LoadCheckpointConfig", "Log", + "LogLevel", "LoopsCheckpoint", + "LoopsCheckpointConfig", "LoopsCheckpointFilesResponse", "LoopsDeployment", "LoopsDeploymentMetrics", @@ -469,21 +558,39 @@ "LoopsSampler", "LoopsSamplerStatus", "LoopsSession", + "LoopsUserConfig", "MaxScaleDownRate", "Model", + "ModelAPI", + "ModelAPIOrgDetails", + "ModelAPIsRequest", + "ModelAPIsResponse", "ModelApiItem", "ModelApisUsage", "ModelArchiveSource", "ModelConfig", + "ModelMetricDescriptor", + "ModelMetricKind", + "ModelMetricMode", + "ModelMetricUnitHint", + "ModelMetricValueSet", "ModelTombstone", "ModelWeightSnapshot", "Models", + "ModelsRequest", "Name", "Name1", + "Name2", "OrderBy", "PaginationResponse", "PatchInteractiveSessionRequest", "PatchInteractiveSessionResponse", + "PatchLoopsUserConfigRequest", + "PatchLoopsUserConfigResponse", + "PatchOps", + "PatchTeamTrainingGpuCapacityRequest", + "PatchTeamTrainingGpuCapacityResponse", + "PendingJobAheadAtSubmit", "PrepareModelUploadRequest", "PrepareModelUploadResponse", "PromoteRequest", @@ -491,23 +598,23 @@ "PromoteToEnvironmentRequest", "PromotionCleanupStrategy", "PromotionSettings", + "QueueEvent", "RateLimit", "RateLimitUnit", "RecreateTrainingJobResponse", "RegisterAPIKeyRequest", "RegisterAPIKeyResponse", "RegistrySecretDockerAuth", + "Replica", + "RequestId", "ResourceKind", "ResponseTimeDatapoint", "RetryDeploymentResponse", "RollingDeployConfig", "RollingDeployStrategy", - "SamplingServer", - "SearchTrainersRequest", - "SearchTrainersResponse", + "SearchPattern", "SearchTrainingJobsRequest", "SearchTrainingJobsResponse", - "SearchedTrainer", "Secret", "SecretReference", "SecretTombstone", @@ -527,14 +634,19 @@ "Subtotal7", "Subtotal8", "SupportedModel", + "SurchargeCost", + "SurchargeCost1", + "SyncDeploymentPatchesRequest", + "SyncDeploymentPatchesResponse", + "Target", + "Targets", "Team", + "TeamTrainingGpuCapacityItem", "Teams", + "TeamsRequest", "TerminateReplicaResponse", "Total", "TrainerCheckpointTarget", - "TrainerServer", - "TrainerServerCheckpoint", - "TrainerSession", "TrainingGpuCapacityItem", "TrainingItem", "TrainingJob", @@ -556,6 +668,9 @@ "UpdateChainletEnvironmentAutoscalingSettingsRequest", "UpdateChainletEnvironmentInstanceTypeRequest", "UpdateChainletEnvironmentInstanceTypeResponse", + "UpdateEndpointRequest", + "UpdateEnvironmentGroupManageAccess", + "UpdateEnvironmentGroupRequest", "UpdateEnvironmentRequest", "UpdateGroupMetadata", "UpdateGroupRequest", @@ -563,6 +678,8 @@ "UpdateLibraryListingVersionRequest", "UpdatePromotionSettings", "UpdateRollingDeployConfig", + "UpdateTrainingJobRequest", + "UpdateTrainingJobResponse", "UpsertSecretRequest", "UpsertTrainingProject", "UpsertTrainingProjectRequest", @@ -573,6 +690,9 @@ "UsageSummaryRequest", "User", "UserInfo", + "UsersRequest", + "UsersResponse", + "V1AvailabilityModel", "V1InteractiveSessionAuthProvider", "V1InteractiveSessionProvider", "V1InteractiveSessionTrigger", diff --git a/baseten/client/managementapi/_client.py b/baseten/client/managementapi/_client.py index d5692f9..45a2d6e 100644 --- a/baseten/client/managementapi/_client.py +++ b/baseten/client/managementapi/_client.py @@ -22,12 +22,13 @@ ChainEnvironment, ChainTombstone, Chains, - CheckpointSearchRequest, - CheckpointSearchResponse, CreateAPIKeyRequest, CreateApiKeyForGroupRequest, CreateApiKeyForGroupResponse, CreateChainEnvironmentRequest, + CreateDeploymentPatchRequest, + CreateDeploymentPatchResponse, + CreateEndpointRequest, CreateEnvironmentRequest, CreateGroupRequest, CreateLLMModelRequest, @@ -38,17 +39,10 @@ CreateLoopsRunResponse, CreateLoopsSamplerRequest, CreateLoopsSamplerResponse, - CreateLoopsSessionRequest, CreateLoopsSessionResponse, CreateModelDeploymentRequest, CreateModelRequest, CreateModelWeightSnapshotRequest, - CreateSamplingServerRequest, - CreateSamplingServerResponse, - CreateTrainerServerRequest, - CreateTrainerServerResponse, - CreateTrainerSessionRequest, - CreateTrainerSessionResponse, CreateTrainingJobRequest, CreateTrainingJobResponse, CreatedModelDeployment, @@ -60,13 +54,19 @@ Deployments, DownloadDeploymentResponse, DownloadTrainingJobResponse, + Endpoint, + EndpointTombstone, + EndpointsResponse, Environment, + EnvironmentGroup, + EnvironmentGroups, Environments, GatewayKeyInfo, GetAuthCodesResponse, GetBlobCredentialsResponse, GetCacheSummaryResponse, GetDeploymentLogsRequest, + GetDeploymentPatchesStateResponse, GetLogsResponse, GetLoopsCapabilitiesResponse, GetLoopsDeploymentMetricsRequest, @@ -75,14 +75,15 @@ GetLoopsRunResponse, GetLoopsSamplerResponse, GetLoopsSessionResponse, - GetTrainerServerCheckpointFilesResponse, - GetTrainerServerCheckpointsResponse, + GetLoopsUserConfigResponse, + GetModelMetricsResponse, GetTrainingGpuCapacityResponse, GetTrainingJobCheckpointFilesResponse, GetTrainingJobCheckpointsResponse, GetTrainingJobLogsRequest, GetTrainingJobMetricsRequest, GetTrainingJobMetricsResponse, + GetTrainingJobQueueContextResponse, GetTrainingJobResponse, GetTrainingProjectResponse, Group, @@ -105,11 +106,17 @@ ListTrainingProjectsResponse, LoopsCheckpointFilesResponse, Model, + ModelAPI, + ModelAPIsResponse, ModelTombstone, ModelWeightSnapshot, Models, PatchInteractiveSessionRequest, PatchInteractiveSessionResponse, + PatchLoopsUserConfigRequest, + PatchLoopsUserConfigResponse, + PatchTeamTrainingGpuCapacityRequest, + PatchTeamTrainingGpuCapacityResponse, PrepareModelUploadRequest, PrepareModelUploadResponse, PromoteRequest, @@ -119,8 +126,6 @@ RegisterAPIKeyRequest, RegisterAPIKeyResponse, RetryDeploymentResponse, - SearchTrainersRequest, - SearchTrainersResponse, SearchTrainingJobsRequest, SearchTrainingJobsResponse, Secret, @@ -131,6 +136,9 @@ SignalPromotionResponse, StopTrainingJobRequest, StopTrainingJobResponse, + SyncDeploymentPatchesRequest, + SyncDeploymentPatchesResponse, + Team, Teams, TerminateReplicaResponse, TrainingJobTombstone, @@ -142,15 +150,20 @@ UpdateChainletEnvironmentAutoscalingSettingsRequest, UpdateChainletEnvironmentInstanceTypeRequest, UpdateChainletEnvironmentInstanceTypeResponse, + UpdateEndpointRequest, + UpdateEnvironmentGroupRequest, UpdateEnvironmentRequest, UpdateGroupRequest, UpdateLibraryListingRequest, UpdateLibraryListingVersionRequest, + UpdateTrainingJobRequest, + UpdateTrainingJobResponse, UpsertSecretRequest, UpsertTrainingProjectRequest, UpsertTrainingProjectResponse, UsageSummary, UserInfo, + UsersResponse, ValidateLoopsCheckpointRequest, ValidateLoopsCheckpointResponse, ) @@ -233,6 +246,20 @@ def delete_chains_deployments( ), ) + def delete_gateway_endpoints(self, *, endpoint_id: str) -> EndpointTombstone: + """Deletes a Gateway endpoint""" + return self._do_json( + EndpointTombstone, + _ApiRequest( + method="DELETE", + path_fmt="/v1/gateway/endpoints/{}", + path_args=[endpoint_id], + body=None, + success_code=200, + error_codes=None, + ), + ) + def delete_library_listings( self, *, user_defined_listing_id: str ) -> LibraryListingTombstone: @@ -344,7 +371,7 @@ def delete_teams_secrets( def delete_training_projects( self, *, training_project_id: str ) -> TrainingProjectTombstone: - """Delete a training project.""" + """Deletes a training project""" return self._do_json( TrainingProjectTombstone, _ApiRequest( @@ -360,7 +387,7 @@ def delete_training_projects( def delete_training_projects_jobs( self, *, training_project_id: str, training_job_id: str ) -> TrainingJobTombstone: - """Delete a training job.""" + """Deletes a training job""" return self._do_json( TrainingJobTombstone, _ApiRequest( @@ -374,7 +401,7 @@ def delete_training_projects_jobs( ) def get_api_keys(self) -> APIKeys: - """Lists the user's API keys (metadata only, no plain text keys)""" + """Lists API keys (metadata only, no plain text keys)""" return self._do_json( APIKeys, _ApiRequest( @@ -402,7 +429,7 @@ def get_billing_usage_summary(self) -> UsageSummary: ) def get_blobs_credentials_model(self) -> GetBlobCredentialsResponse: - """Get blob credentials for models.""" + """Gets blob credentials for models""" return self._do_json( GetBlobCredentialsResponse, _ApiRequest( @@ -416,7 +443,7 @@ def get_blobs_credentials_model(self) -> GetBlobCredentialsResponse: ) def get_blobs_credentials_train(self) -> GetBlobCredentialsResponse: - """Get blob credentials for training.""" + """Gets blob credentials for training""" return self._do_json( GetBlobCredentialsResponse, _ApiRequest( @@ -490,7 +517,7 @@ def get_chains_deployments_chain_deployment_id( def get_chains_deployments_chainlets_logs( self, *, chain_id: str, chain_deployment_id: str, chainlet_id: str ) -> GetLogsResponse: - """Gets the logs for a chainlet within a chain deployment.""" + """Gets the logs for a chainlet within a chain deployment""" return self._do_json( GetLogsResponse, _ApiRequest( @@ -504,7 +531,7 @@ def get_chains_deployments_chainlets_logs( ) def get_chains_environments(self, *, chain_id: str) -> Environments: - """Get all chain environments""" + """Gets all chain environments""" return self._do_json( Environments, _ApiRequest( @@ -520,7 +547,7 @@ def get_chains_environments(self, *, chain_id: str) -> Environments: def get_chains_environments_env_name( self, *, chain_id: str, env_name: str ) -> ChainEnvironment: - """Get a chain environment's details""" + """Gets a chain environment's details""" return self._do_json( ChainEnvironment, _ApiRequest( @@ -533,8 +560,64 @@ def get_chains_environments_env_name( ), ) + def get_environment_groups(self) -> EnvironmentGroups: + """Lists environment groups""" + return self._do_json( + EnvironmentGroups, + _ApiRequest( + method="GET", + path_fmt="/v1/environment_groups", + path_args=[], + body=None, + success_code=200, + error_codes=None, + ), + ) + + def get_environment_groups_env_name(self, *, env_name: str) -> EnvironmentGroup: + """Gets an environment group by name""" + return self._do_json( + EnvironmentGroup, + _ApiRequest( + method="GET", + path_fmt="/v1/environment_groups/{}", + path_args=[env_name], + body=None, + success_code=200, + error_codes=None, + ), + ) + + def get_gateway_endpoints(self) -> EndpointsResponse: + """Lists Gateway endpoints""" + return self._do_json( + EndpointsResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/gateway/endpoints", + path_args=[], + body=None, + success_code=200, + error_codes=None, + ), + ) + + def get_gateway_endpoints_endpoint_id(self, *, endpoint_id: str) -> Endpoint: + """Gets a Gateway endpoint""" + return self._do_json( + Endpoint, + _ApiRequest( + method="GET", + path_fmt="/v1/gateway/endpoints/{}", + path_args=[endpoint_id], + body=None, + success_code=200, + error_codes=None, + ), + ) + def get_gateway_groups(self) -> GroupsResponse: - """List groups""" + """Lists groups""" return self._do_json( GroupsResponse, _ApiRequest( @@ -548,7 +631,7 @@ def get_gateway_groups(self) -> GroupsResponse: ) def get_gateway_groups_api_keys(self, *, group_id: str) -> KeysForGroupResponse: - """List API keys for a group""" + """Lists API keys for a group""" return self._do_json( KeysForGroupResponse, _ApiRequest( @@ -564,7 +647,7 @@ def get_gateway_groups_api_keys(self, *, group_id: str) -> KeysForGroupResponse: def get_gateway_groups_api_keys_api_key_prefix( self, *, group_id: str, api_key_prefix: str ) -> GatewayKeyInfo: - """Get an API key for a group""" + """Gets an API key for a group""" return self._do_json( GatewayKeyInfo, _ApiRequest( @@ -578,7 +661,7 @@ def get_gateway_groups_api_keys_api_key_prefix( ) def get_gateway_groups_group_id(self, *, group_id: str) -> Group: - """Get a group""" + """Gets a group""" return self._do_json( Group, _ApiRequest( @@ -592,7 +675,7 @@ def get_gateway_groups_group_id(self, *, group_id: str) -> Group: ) def get_instance_type_prices(self) -> InstanceTypePrices: - """Gets prices for available instance types.""" + """Gets prices for available instance types""" return self._do_json( InstanceTypePrices, _ApiRequest( @@ -682,7 +765,7 @@ def get_library_listings_versions_version_tag( ) def get_loops_capabilities(self) -> GetLoopsCapabilitiesResponse: - """Get Loops server capabilities.""" + """Gets Loops server capabilities""" return self._do_json( GetLoopsCapabilitiesResponse, _ApiRequest( @@ -696,7 +779,7 @@ def get_loops_capabilities(self) -> GetLoopsCapabilitiesResponse: ) def get_loops_checkpoints(self) -> ListLoopsCheckpointsResponse: - """List Loops checkpoints.""" + """Lists Loops checkpoints""" return self._do_json( ListLoopsCheckpointsResponse, _ApiRequest( @@ -712,7 +795,7 @@ def get_loops_checkpoints(self) -> ListLoopsCheckpointsResponse: def get_loops_checkpoints_files( self, *, checkpoint_id: str ) -> LoopsCheckpointFilesResponse: - """Get Loops checkpoint files.""" + """Gets Loops checkpoint files""" return self._do_json( LoopsCheckpointFilesResponse, _ApiRequest( @@ -726,7 +809,7 @@ def get_loops_checkpoints_files( ) def get_loops_deployments(self) -> ListLoopsDeploymentsResponse: - """List Loops deployments.""" + """Lists Loops deployments""" return self._do_json( ListLoopsDeploymentsResponse, _ApiRequest( @@ -742,7 +825,7 @@ def get_loops_deployments(self) -> ListLoopsDeploymentsResponse: def get_loops_deployments_deployment_id( self, *, deployment_id: str ) -> GetLoopsDeploymentResponse: - """Get a Loops deployment.""" + """Gets a Loops deployment""" return self._do_json( GetLoopsDeploymentResponse, _ApiRequest( @@ -756,7 +839,7 @@ def get_loops_deployments_deployment_id( ) def get_loops_deployments_logs(self, *, deployment_id: str) -> GetLogsResponse: - """Get logs for a Loops trainer deployment.""" + """Gets logs for a Loops trainer deployment""" return self._do_json( GetLogsResponse, _ApiRequest( @@ -770,7 +853,7 @@ def get_loops_deployments_logs(self, *, deployment_id: str) -> GetLogsResponse: ) def get_loops_runs(self) -> ListLoopsRunsResponse: - """List Loops runs.""" + """Lists Loops runs""" return self._do_json( ListLoopsRunsResponse, _ApiRequest( @@ -784,7 +867,7 @@ def get_loops_runs(self) -> ListLoopsRunsResponse: ) def get_loops_runs_run_id(self, *, run_id: str) -> GetLoopsRunResponse: - """Get a Loops run.""" + """Gets a Loops run""" return self._do_json( GetLoopsRunResponse, _ApiRequest( @@ -798,7 +881,7 @@ def get_loops_runs_run_id(self, *, run_id: str) -> GetLoopsRunResponse: ) def get_loops_samplers(self) -> ListLoopsSamplersResponse: - """List Loops samplers.""" + """Lists Loops samplers""" return self._do_json( ListLoopsSamplersResponse, _ApiRequest( @@ -814,7 +897,7 @@ def get_loops_samplers(self) -> ListLoopsSamplersResponse: def get_loops_samplers_sampler_id( self, *, sampler_id: str ) -> GetLoopsSamplerResponse: - """Get a Loops sampler.""" + """Gets a Loops sampler""" return self._do_json( GetLoopsSamplerResponse, _ApiRequest( @@ -828,7 +911,7 @@ def get_loops_samplers_sampler_id( ) def get_loops_sessions(self, *, session_id: str) -> GetLoopsSessionResponse: - """Get a Loops session.""" + """Gets a Loops session""" return self._do_json( GetLoopsSessionResponse, _ApiRequest( @@ -841,8 +924,50 @@ def get_loops_sessions(self, *, session_id: str) -> GetLoopsSessionResponse: ), ) + def get_loops_user_config(self) -> GetLoopsUserConfigResponse: + """Gets the caller's Loops user config""" + return self._do_json( + GetLoopsUserConfigResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/loops/user_config", + path_args=[], + body=None, + success_code=200, + error_codes=None, + ), + ) + + def get_model_apis(self) -> ModelAPIsResponse: + """Lists Model APIs""" + return self._do_json( + ModelAPIsResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/model_apis", + path_args=[], + body=None, + success_code=200, + error_codes=None, + ), + ) + + def get_model_apis_model_api_name(self, *, model_api_name: str) -> ModelAPI: + """Gets a Model API""" + return self._do_json( + ModelAPI, + _ApiRequest( + method="GET", + path_fmt="/v1/model_apis/{}", + path_args=[model_api_name], + body=None, + success_code=200, + error_codes=None, + ), + ) + def get_model_apis_snapshots(self) -> ModelWeightSnapshot: - """Get the latest model weight snapshot""" + """Gets the latest model weight snapshot""" return self._do_json( ModelWeightSnapshot, _ApiRequest( @@ -858,7 +983,7 @@ def get_model_apis_snapshots(self) -> ModelWeightSnapshot: def get_model_apis_snapshots_model_id( self, *, model_id: str ) -> ModelWeightSnapshot: - """Get the latest model weight snapshot""" + """Gets the latest model weight snapshot""" return self._do_json( ModelWeightSnapshot, _ApiRequest( @@ -964,7 +1089,7 @@ def get_models_deployments_download( def get_models_deployments_logs( self, *, model_id: str, deployment_id: str ) -> GetLogsResponse: - """Gets the logs for a model deployment.""" + """Gets the logs for a model deployment""" return self._do_json( GetLogsResponse, _ApiRequest( @@ -977,6 +1102,38 @@ def get_models_deployments_logs( ), ) + def get_models_deployments_metrics( + self, *, model_id: str, deployment_id: str + ) -> GetModelMetricsResponse: + """Gets the metrics for a model deployment""" + return self._do_json( + GetModelMetricsResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/models/{}/deployments/{}/metrics", + path_args=[model_id, deployment_id], + body=None, + success_code=200, + error_codes=None, + ), + ) + + def get_models_deployments_patches_state( + self, *, model_id: str, deployment_id: str + ) -> GetDeploymentPatchesStateResponse: + """Gets a development deployment's patch state""" + return self._do_json( + GetDeploymentPatchesStateResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/models/{}/deployments/{}/patches/state", + path_args=[model_id, deployment_id], + body=None, + success_code=200, + error_codes=None, + ), + ) + def get_models_deployments_production(self, *, model_id: str) -> Deployment: """Gets a model's production deployment""" return self._do_json( @@ -992,7 +1149,7 @@ def get_models_deployments_production(self, *, model_id: str) -> Deployment: ) def get_models_environments(self, *, model_id: str) -> Environments: - """Get all environments""" + """Gets all environments""" return self._do_json( Environments, _ApiRequest( @@ -1008,7 +1165,7 @@ def get_models_environments(self, *, model_id: str) -> Environments: def get_models_environments_env_name( self, *, model_id: str, env_name: str ) -> Environment: - """Get an environment's details""" + """Gets an environment's details""" return self._do_json( Environment, _ApiRequest( @@ -1021,6 +1178,38 @@ def get_models_environments_env_name( ), ) + def get_models_environments_logs( + self, *, model_id: str, env_name: str + ) -> GetLogsResponse: + """Gets the logs for a model environment""" + return self._do_json( + GetLogsResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/models/{}/environments/{}/logs", + path_args=[model_id, env_name], + body=None, + success_code=200, + error_codes=None, + ), + ) + + def get_models_environments_metrics( + self, *, model_id: str, env_name: str + ) -> GetModelMetricsResponse: + """Gets the metrics for a model environment.""" + return self._do_json( + GetModelMetricsResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/models/{}/environments/{}/metrics", + path_args=[model_id, env_name], + body=None, + success_code=200, + error_codes=None, + ), + ) + def get_models_model_id(self, *, model_id: str) -> Model: """Gets a model by ID""" return self._do_json( @@ -1063,6 +1252,36 @@ def get_teams(self) -> Teams: ), ) + def get_teams_environment_groups(self, *, team_id: str) -> EnvironmentGroups: + """Lists environment groups""" + return self._do_json( + EnvironmentGroups, + _ApiRequest( + method="GET", + path_fmt="/v1/teams/{}/environment_groups", + path_args=[team_id], + body=None, + success_code=200, + error_codes=None, + ), + ) + + def get_teams_environment_groups_env_name( + self, *, team_id: str, env_name: str + ) -> EnvironmentGroup: + """Gets an environment group by name""" + return self._do_json( + EnvironmentGroup, + _ApiRequest( + method="GET", + path_fmt="/v1/teams/{}/environment_groups/{}", + path_args=[team_id, env_name], + body=None, + success_code=200, + error_codes=None, + ), + ) + def get_teams_models(self, *, team_id: str) -> Models: """Gets all models""" return self._do_json( @@ -1091,46 +1310,44 @@ def get_teams_secrets(self, *, team_id: str) -> Secrets: ), ) - def get_trainer_sessions_trainers_checkpoints( - self, *, session_id: str, trainer_id: str - ) -> GetTrainerServerCheckpointsResponse: - """List trainer server checkpoints.""" + def get_teams_team_id(self, *, team_id: str) -> Team: + """Gets a team by ID""" return self._do_json( - GetTrainerServerCheckpointsResponse, + Team, _ApiRequest( method="GET", - path_fmt="/v1/trainer_sessions/{}/trainers/{}/checkpoints", - path_args=[session_id, trainer_id], + path_fmt="/v1/teams/{}", + path_args=[team_id], body=None, success_code=200, error_codes=None, ), ) - def get_trainer_sessions_trainers_checkpoints_files( - self, *, session_id: str, trainer_id: str, checkpoint_id: str - ) -> GetTrainerServerCheckpointFilesResponse: - """Get trainer server checkpoint files.""" + def get_training_capacity(self) -> GetTrainingGpuCapacityResponse: + """Gets training GPU capacity""" return self._do_json( - GetTrainerServerCheckpointFilesResponse, + GetTrainingGpuCapacityResponse, _ApiRequest( method="GET", - path_fmt="/v1/trainer_sessions/{}/trainers/{}/checkpoints/{}/files", - path_args=[session_id, trainer_id, checkpoint_id], + path_fmt="/v1/training/capacity", + path_args=[], body=None, success_code=200, error_codes=None, ), ) - def get_training_capacity(self) -> GetTrainingGpuCapacityResponse: - """Get training GPU capacity.""" + def get_training_jobs_queue_context( + self, *, training_job_id: str + ) -> GetTrainingJobQueueContextResponse: + """Reconstructs queue context for a training job""" return self._do_json( - GetTrainingGpuCapacityResponse, + GetTrainingJobQueueContextResponse, _ApiRequest( method="GET", - path_fmt="/v1/training/capacity", - path_args=[], + path_fmt="/v1/training/jobs/{}/queue_context", + path_args=[training_job_id], body=None, success_code=200, error_codes=None, @@ -1138,7 +1355,7 @@ def get_training_capacity(self) -> GetTrainingGpuCapacityResponse: ) def get_training_projects(self) -> ListTrainingProjectsResponse: - """List training projects.""" + """Lists training projects""" return self._do_json( ListTrainingProjectsResponse, _ApiRequest( @@ -1154,7 +1371,7 @@ def get_training_projects(self) -> ListTrainingProjectsResponse: def get_training_projects_cache_summary( self, *, training_project_id: str ) -> GetCacheSummaryResponse: - """Get training project cache summary.""" + """Gets training project cache summary""" return self._do_json( GetCacheSummaryResponse, _ApiRequest( @@ -1170,7 +1387,7 @@ def get_training_projects_cache_summary( def get_training_projects_jobs( self, *, training_project_id: str ) -> ListTrainingJobsResponse: - """List training jobs.""" + """Lists training jobs""" return self._do_json( ListTrainingJobsResponse, _ApiRequest( @@ -1186,7 +1403,7 @@ def get_training_projects_jobs( def get_training_projects_jobs_auth_codes( self, *, training_project_id: str, training_job_id: str ) -> GetAuthCodesResponse: - """Get auth codes for a training job.""" + """Gets auth codes for a training job""" return self._do_json( GetAuthCodesResponse, _ApiRequest( @@ -1202,7 +1419,7 @@ def get_training_projects_jobs_auth_codes( def get_training_projects_jobs_checkpoint_files( self, *, training_project_id: str, training_job_id: str ) -> GetTrainingJobCheckpointFilesResponse: - """Get training job checkpoint files.""" + """Gets training job checkpoint files""" return self._do_json( GetTrainingJobCheckpointFilesResponse, _ApiRequest( @@ -1218,7 +1435,7 @@ def get_training_projects_jobs_checkpoint_files( def get_training_projects_jobs_checkpoints( self, *, training_project_id: str, training_job_id: str ) -> GetTrainingJobCheckpointsResponse: - """Get training job checkpoints.""" + """Gets training job checkpoints""" return self._do_json( GetTrainingJobCheckpointsResponse, _ApiRequest( @@ -1234,7 +1451,7 @@ def get_training_projects_jobs_checkpoints( def get_training_projects_jobs_download( self, *, training_project_id: str, training_job_id: str ) -> DownloadTrainingJobResponse: - """Get the uploaded training job as a S3 Artifact""" + """Gets presigned URLs for a training job's artifacts""" return self._do_json( DownloadTrainingJobResponse, _ApiRequest( @@ -1250,7 +1467,7 @@ def get_training_projects_jobs_download( def get_training_projects_jobs_logs( self, *, training_project_id: str, training_job_id: str ) -> GetLogsResponse: - """Get the logs for a training job.""" + """Gets the logs for a training job""" return self._do_json( GetLogsResponse, _ApiRequest( @@ -1266,7 +1483,7 @@ def get_training_projects_jobs_logs( def get_training_projects_jobs_metrics( self, *, training_project_id: str, training_job_id: str ) -> GetTrainingJobMetricsResponse: - """Get the metrics for a training job.""" + """Gets the metrics for a training job""" return self._do_json( GetTrainingJobMetricsResponse, _ApiRequest( @@ -1282,7 +1499,7 @@ def get_training_projects_jobs_metrics( def get_training_projects_jobs_training_job_id( self, *, training_project_id: str, training_job_id: str ) -> GetTrainingJobResponse: - """Get a training job.""" + """Gets a training job""" return self._do_json( GetTrainingJobResponse, _ApiRequest( @@ -1298,7 +1515,7 @@ def get_training_projects_jobs_training_job_id( def get_training_projects_training_project_id( self, *, training_project_id: str ) -> GetTrainingProjectResponse: - """Get a training project.""" + """Gets a training project""" return self._do_json( GetTrainingProjectResponse, _ApiRequest( @@ -1311,7 +1528,35 @@ def get_training_projects_training_project_id( ), ) - def get_users(self, *, user_id: str) -> UserInfo: + def get_users(self) -> UsersResponse: + """Lists users in the workspace""" + return self._do_json( + UsersResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/users", + path_args=[], + body=None, + success_code=200, + error_codes=None, + ), + ) + + def get_users_me(self) -> UserInfo: + """Gets the authenticated user""" + return self._do_json( + UserInfo, + _ApiRequest( + method="GET", + path_fmt="/v1/users/me", + path_args=[], + body=None, + success_code=200, + error_codes=None, + ), + ) + + def get_users_user_id(self, *, user_id: str) -> UserInfo: """Gets a user by ID""" return self._do_json( UserInfo, @@ -1328,7 +1573,7 @@ def get_users(self, *, user_id: str) -> UserInfo: def patch_chains_environments( self, *, chain_id: str, env_name: str, body: UpdateChainEnvironmentRequest ) -> UpdateChainEnvironmentResponse: - """Update a chain environment's settings""" + """Updates a chain environment's settings""" return self._do_json( UpdateChainEnvironmentResponse, _ApiRequest( @@ -1348,7 +1593,7 @@ def patch_chains_environments_chainlet_settings_autoscaling_settings( env_name: str, body: UpdateChainletEnvironmentAutoscalingSettingsRequest, ) -> UpdateAutoscalingSettingsResponse: - """Update a chainlet environment's autoscaling settings""" + """Updates a chainlet environment's autoscaling settings""" return self._do_json( UpdateAutoscalingSettingsResponse, _ApiRequest( @@ -1361,8 +1606,40 @@ def patch_chains_environments_chainlet_settings_autoscaling_settings( ), ) + def patch_environment_groups( + self, *, env_name: str, body: UpdateEnvironmentGroupRequest + ) -> EnvironmentGroup: + """Updates an environment group's restriction settings""" + return self._do_json( + EnvironmentGroup, + _ApiRequest( + method="PATCH", + path_fmt="/v1/environment_groups/{}", + path_args=[env_name], + body=body, + success_code=200, + error_codes=None, + ), + ) + + def patch_gateway_endpoints( + self, *, endpoint_id: str, body: UpdateEndpointRequest + ) -> Endpoint: + """Updates a Gateway endpoint""" + return self._do_json( + Endpoint, + _ApiRequest( + method="PATCH", + path_fmt="/v1/gateway/endpoints/{}", + path_args=[endpoint_id], + body=body, + success_code=200, + error_codes=None, + ), + ) + def patch_gateway_groups(self, *, group_id: str, body: UpdateGroupRequest) -> Group: - """Update a group""" + """Updates a group""" return self._do_json( Group, _ApiRequest( @@ -1411,6 +1688,22 @@ def patch_library_listings_versions( ), ) + def patch_loops_user_config( + self, *, body: PatchLoopsUserConfigRequest + ) -> PatchLoopsUserConfigResponse: + """Patches the caller's Loops user config""" + return self._do_json( + PatchLoopsUserConfigResponse, + _ApiRequest( + method="PATCH", + path_fmt="/v1/loops/user_config", + path_args=[], + body=body, + success_code=200, + error_codes=None, + ), + ) + def patch_models_deployments_autoscaling_settings( self, *, model_id: str, deployment_id: str, body: UpdateAutoscalingSettings ) -> UpdateAutoscalingSettingsResponse: @@ -1462,7 +1755,7 @@ def patch_models_deployments_production_autoscaling_settings( def patch_models_environments( self, *, model_id: str, env_name: str, body: UpdateEnvironmentRequest ) -> UpdateAutoscalingSettingsResponse: - """Update an environment's settings""" + """Updates an environment's settings""" return self._do_json( UpdateAutoscalingSettingsResponse, _ApiRequest( @@ -1475,6 +1768,58 @@ def patch_models_environments( ), ) + def patch_teams_environment_groups( + self, *, team_id: str, env_name: str, body: UpdateEnvironmentGroupRequest + ) -> EnvironmentGroup: + """Updates an environment group's restriction settings""" + return self._do_json( + EnvironmentGroup, + _ApiRequest( + method="PATCH", + path_fmt="/v1/teams/{}/environment_groups/{}", + path_args=[team_id, env_name], + body=body, + success_code=200, + error_codes=None, + ), + ) + + def patch_training_capacity( + self, *, body: PatchTeamTrainingGpuCapacityRequest + ) -> PatchTeamTrainingGpuCapacityResponse: + """Sets a team's training GPU capacity""" + return self._do_json( + PatchTeamTrainingGpuCapacityResponse, + _ApiRequest( + method="PATCH", + path_fmt="/v1/training/capacity", + path_args=[], + body=body, + success_code=200, + error_codes=None, + ), + ) + + def patch_training_projects_jobs( + self, + *, + training_project_id: str, + training_job_id: str, + body: UpdateTrainingJobRequest, + ) -> UpdateTrainingJobResponse: + """Updates a training job""" + return self._do_json( + UpdateTrainingJobResponse, + _ApiRequest( + method="PATCH", + path_fmt="/v1/training_projects/{}/jobs/{}", + path_args=[training_project_id, training_job_id], + body=body, + success_code=200, + error_codes=None, + ), + ) + def patch_training_projects_jobs_interactive_sessions( self, *, @@ -1483,7 +1828,7 @@ def patch_training_projects_jobs_interactive_sessions( session_id: str, body: PatchInteractiveSessionRequest, ) -> PatchInteractiveSessionResponse: - """Patch an interactive session.""" + """Patches an interactive session""" return self._do_json( PatchInteractiveSessionResponse, _ApiRequest( @@ -1529,7 +1874,7 @@ def post_chains_deployments_deactivate( def post_chains_environments( self, *, chain_id: str, body: CreateChainEnvironmentRequest ) -> ChainEnvironment: - """Create a chain environment""" + """Creates a chain environment""" return self._do_json( ChainEnvironment, _ApiRequest( @@ -1549,7 +1894,7 @@ def post_chains_environments_chainlet_settings_instance_types_update( env_name: str, body: UpdateChainletEnvironmentInstanceTypeRequest, ) -> UpdateChainletEnvironmentInstanceTypeResponse: - """Update a chainlet environment's instance type settings.""" + """Updates a chainlet environment's instance type settings""" return self._do_json( UpdateChainletEnvironmentInstanceTypeResponse, _ApiRequest( @@ -1578,8 +1923,22 @@ def post_chains_environments_promote( ), ) + def post_gateway_endpoints(self, *, body: CreateEndpointRequest) -> Endpoint: + """Creates a Gateway endpoint""" + return self._do_json( + Endpoint, + _ApiRequest( + method="POST", + path_fmt="/v1/gateway/endpoints", + path_args=[], + body=body, + success_code=200, + error_codes=None, + ), + ) + def post_gateway_groups(self, *, body: CreateGroupRequest) -> Group: - """Create a group""" + """Creates a group""" return self._do_json( Group, _ApiRequest( @@ -1595,7 +1954,7 @@ def post_gateway_groups(self, *, body: CreateGroupRequest) -> Group: def post_gateway_groups_api_keys( self, *, group_id: str, body: CreateApiKeyForGroupRequest ) -> CreateApiKeyForGroupResponse: - """Create an API key for a group""" + """Creates an API key for a group""" return self._do_json( CreateApiKeyForGroupResponse, _ApiRequest( @@ -1611,7 +1970,7 @@ def post_gateway_groups_api_keys( def post_gateway_groups_api_keys_register( self, *, group_id: str, body: RegisterAPIKeyRequest ) -> RegisterAPIKeyResponse: - """Register an API key for a group""" + """Registers an API key for a group""" return self._do_json( RegisterAPIKeyResponse, _ApiRequest( @@ -1657,7 +2016,7 @@ def post_library_listings_versions( ) def post_llm_models(self, *, body: CreateLLMModelRequest) -> LLMModelHandle: - """Creates a new BIS LLM deployment""" + """Creates a new BIS-LLM deployment""" return self._do_json( LLMModelHandle, _ApiRequest( @@ -1673,7 +2032,7 @@ def post_llm_models(self, *, body: CreateLLMModelRequest) -> LLMModelHandle: def post_llm_models_deployments( self, *, model_id: str, body: CreateLLMModelVersionRequest ) -> LLMModelHandle: - """Creates a new BIS LLM deployment version""" + """Creates a new BIS-LLM deployment version""" return self._do_json( LLMModelHandle, _ApiRequest( @@ -1689,7 +2048,7 @@ def post_llm_models_deployments( def post_loops_checkpoints_validate( self, *, body: ValidateLoopsCheckpointRequest ) -> ValidateLoopsCheckpointResponse: - """Validate a Loops checkpoint bt:// URI.""" + """Validates a Loops checkpoint bt:// URI""" return self._do_json( ValidateLoopsCheckpointResponse, _ApiRequest( @@ -1705,7 +2064,7 @@ def post_loops_checkpoints_validate( def post_loops_deployments_deactivate( self, *, deployment_id: str ) -> DeactivateLoopsDeploymentResponse: - """Deactivate a Loops deployment.""" + """Deactivates a Loops deployment""" return self._do_json( DeactivateLoopsDeploymentResponse, _ApiRequest( @@ -1721,7 +2080,7 @@ def post_loops_deployments_deactivate( def post_loops_deployments_metrics( self, *, deployment_id: str, body: GetLoopsDeploymentMetricsRequest ) -> GetLoopsDeploymentMetricsResponse: - """Get metrics for a Loops trainer deployment.""" + """Gets metrics for a Loops trainer deployment""" return self._do_json( GetLoopsDeploymentMetricsResponse, _ApiRequest( @@ -1735,7 +2094,7 @@ def post_loops_deployments_metrics( ) def post_loops_runs(self, *, body: CreateLoopsRunRequest) -> CreateLoopsRunResponse: - """Create a Loops run.""" + """Creates a Loops run""" return self._do_json( CreateLoopsRunResponse, _ApiRequest( @@ -1751,7 +2110,7 @@ def post_loops_runs(self, *, body: CreateLoopsRunRequest) -> CreateLoopsRunRespo def post_loops_samplers( self, *, body: CreateLoopsSamplerRequest ) -> CreateLoopsSamplerResponse: - """Create a Loops sampler.""" + """Creates a Loops sampler""" return self._do_json( CreateLoopsSamplerResponse, _ApiRequest( @@ -1764,17 +2123,15 @@ def post_loops_samplers( ), ) - def post_loops_sessions( - self, *, body: CreateLoopsSessionRequest - ) -> CreateLoopsSessionResponse: - """Create a Loops session.""" + def post_loops_sessions(self) -> CreateLoopsSessionResponse: + """Creates a Loops session""" return self._do_json( CreateLoopsSessionResponse, _ApiRequest( method="POST", path_fmt="/v1/loops/sessions", path_args=[], - body=body, + body=None, success_code=200, error_codes=None, ), @@ -1783,7 +2140,7 @@ def post_loops_sessions( def post_model_apis_snapshots( self, *, body: CreateModelWeightSnapshotRequest ) -> ModelWeightSnapshot: - """Create a model weight snapshot""" + """Creates a model weight snapshot""" return self._do_json( ModelWeightSnapshot, _ApiRequest( @@ -1799,7 +2156,7 @@ def post_model_apis_snapshots( def post_model_apis_snapshots_model_id( self, *, model_id: str, body: CreateModelWeightSnapshotRequest ) -> ModelWeightSnapshot: - """Create a model weight snapshot""" + """Creates a model weight snapshot""" return self._do_json( ModelWeightSnapshot, _ApiRequest( @@ -1941,7 +2298,7 @@ def post_models_deployments_development_retry( def post_models_deployments_logs( self, *, model_id: str, deployment_id: str, body: GetDeploymentLogsRequest ) -> GetLogsResponse: - """Gets the logs for a model deployment (deprecated; use GET).""" + """Gets the logs for a model deployment (deprecated; use GET)""" return self._do_json( GetLogsResponse, _ApiRequest( @@ -1954,17 +2311,49 @@ def post_models_deployments_logs( ), ) - def post_models_deployments_production_activate( - self, *, model_id: str - ) -> ActivateResponse: - """Activates a production deployment""" + def post_models_deployments_patches( + self, *, model_id: str, deployment_id: str, body: CreateDeploymentPatchRequest + ) -> CreateDeploymentPatchResponse: + """Stages a patch against a development deployment""" return self._do_json( - ActivateResponse, + CreateDeploymentPatchResponse, _ApiRequest( method="POST", - path_fmt="/v1/models/{}/deployments/production/activate", - path_args=[model_id], - body=None, + path_fmt="/v1/models/{}/deployments/{}/patches", + path_args=[model_id, deployment_id], + body=body, + success_code=200, + error_codes=None, + ), + ) + + def post_models_deployments_patches_sync( + self, *, model_id: str, deployment_id: str, body: SyncDeploymentPatchesRequest + ) -> SyncDeploymentPatchesResponse: + """Syncs staged patches to a development deployment""" + return self._do_json( + SyncDeploymentPatchesResponse, + _ApiRequest( + method="POST", + path_fmt="/v1/models/{}/deployments/{}/patches/sync", + path_args=[model_id, deployment_id], + body=body, + success_code=200, + error_codes=None, + ), + ) + + def post_models_deployments_production_activate( + self, *, model_id: str + ) -> ActivateResponse: + """Activates a production deployment""" + return self._do_json( + ActivateResponse, + _ApiRequest( + method="POST", + path_fmt="/v1/models/{}/deployments/production/activate", + path_args=[model_id], + body=None, success_code=200, error_codes=None, ), @@ -2037,7 +2426,7 @@ def post_models_deployments_retry( def post_models_deployments_ssh_sign( self, *, model_id: str, deployment_id: str, body: SignSSHCertificateRequest ) -> SignSSHCertificateResponse: - """Sign an SSH certificate for an inference model.""" + """Signs an SSH certificate for an inference model""" return self._do_json( SignSSHCertificateResponse, _ApiRequest( @@ -2053,7 +2442,7 @@ def post_models_deployments_ssh_sign( def post_models_environments( self, *, model_id: str, body: CreateEnvironmentRequest ) -> Environment: - """Create an environment""" + """Creates an environment""" return self._do_json( Environment, _ApiRequest( @@ -2241,7 +2630,7 @@ def post_teams_api_keys(self, *, team_id: str, body: CreateAPIKeyRequest) -> API def post_teams_llm_models( self, *, team_id: str, body: CreateLLMModelRequest ) -> LLMModelHandle: - """Creates a new BIS LLM deployment""" + """Creates a new BIS-LLM deployment""" return self._do_json( LLMModelHandle, _ApiRequest( @@ -2287,7 +2676,7 @@ def post_teams_secrets(self, *, team_id: str, body: UpsertSecretRequest) -> Secr def post_teams_training_projects( self, *, team_id: str, body: UpsertTrainingProjectRequest ) -> UpsertTrainingProjectResponse: - """Upsert a training project in a specific team.""" + """Upserts a training project in a specific team""" return self._do_json( UpsertTrainingProjectResponse, _ApiRequest( @@ -2300,90 +2689,10 @@ def post_teams_training_projects( ), ) - def post_trainer_sessions( - self, *, body: CreateTrainerSessionRequest - ) -> CreateTrainerSessionResponse: - """Create a trainer session.""" - return self._do_json( - CreateTrainerSessionResponse, - _ApiRequest( - method="POST", - path_fmt="/v1/trainer_sessions", - path_args=[], - body=body, - success_code=200, - error_codes=None, - ), - ) - - def post_trainer_sessions_samplers( - self, *, session_id: str, body: CreateSamplingServerRequest - ) -> CreateSamplingServerResponse: - """Create a sampling server.""" - return self._do_json( - CreateSamplingServerResponse, - _ApiRequest( - method="POST", - path_fmt="/v1/trainer_sessions/{}/samplers", - path_args=[session_id], - body=body, - success_code=200, - error_codes=None, - ), - ) - - def post_trainer_sessions_trainers( - self, *, session_id: str, body: CreateTrainerServerRequest - ) -> CreateTrainerServerResponse: - """Create a trainer server.""" - return self._do_json( - CreateTrainerServerResponse, - _ApiRequest( - method="POST", - path_fmt="/v1/trainer_sessions/{}/trainers", - path_args=[session_id], - body=body, - success_code=200, - error_codes=None, - ), - ) - - def post_trainers_checkpoints_search( - self, *, body: CheckpointSearchRequest - ) -> CheckpointSearchResponse: - """Look up trainer checkpoint info by bt:// URI.""" - return self._do_json( - CheckpointSearchResponse, - _ApiRequest( - method="POST", - path_fmt="/v1/trainers/checkpoints/search", - path_args=[], - body=body, - success_code=200, - error_codes=None, - ), - ) - - def post_trainers_search( - self, *, body: SearchTrainersRequest - ) -> SearchTrainersResponse: - """Search trainers.""" - return self._do_json( - SearchTrainersResponse, - _ApiRequest( - method="POST", - path_fmt="/v1/trainers/search", - path_args=[], - body=body, - success_code=200, - error_codes=None, - ), - ) - def post_training_jobs_search( self, *, body: SearchTrainingJobsRequest ) -> SearchTrainingJobsResponse: - """Search training jobs.""" + """Searches training jobs""" return self._do_json( SearchTrainingJobsResponse, _ApiRequest( @@ -2399,7 +2708,7 @@ def post_training_jobs_search( def post_training_projects( self, *, body: UpsertTrainingProjectRequest ) -> UpsertTrainingProjectResponse: - """Upsert a training project.""" + """Upserts a training project""" return self._do_json( UpsertTrainingProjectResponse, _ApiRequest( @@ -2415,7 +2724,7 @@ def post_training_projects( def post_training_projects_jobs( self, *, training_project_id: str, body: CreateTrainingJobRequest ) -> CreateTrainingJobResponse: - """Create a training job.""" + """Creates a training job""" return self._do_json( CreateTrainingJobResponse, _ApiRequest( @@ -2435,7 +2744,7 @@ def post_training_projects_jobs_logs( training_job_id: str, body: GetTrainingJobLogsRequest, ) -> GetLogsResponse: - """Get the logs for a training job (deprecated; use GET).""" + """Gets the logs for a training job (deprecated; use GET)""" return self._do_json( GetLogsResponse, _ApiRequest( @@ -2455,7 +2764,7 @@ def post_training_projects_jobs_metrics( training_job_id: str, body: GetTrainingJobMetricsRequest, ) -> GetTrainingJobMetricsResponse: - """Get the metrics for a training job (deprecated; use GET).""" + """Gets the metrics for a training job (deprecated; use GET)""" return self._do_json( GetTrainingJobMetricsResponse, _ApiRequest( @@ -2471,7 +2780,7 @@ def post_training_projects_jobs_metrics( def post_training_projects_jobs_recreate( self, *, training_project_id: str, training_job_id: str ) -> RecreateTrainingJobResponse: - """Recreate a training job""" + """Recreates a training job""" return self._do_json( RecreateTrainingJobResponse, _ApiRequest( @@ -2491,7 +2800,7 @@ def post_training_projects_jobs_ssh_sign( training_job_id: str, body: SignSSHCertificateRequest, ) -> SignSSHCertificateResponse: - """Sign an SSH certificate for a training job.""" + """Signs an SSH certificate for a training job""" return self._do_json( SignSSHCertificateResponse, _ApiRequest( @@ -2511,7 +2820,7 @@ def post_training_projects_jobs_stop( training_job_id: str, body: StopTrainingJobRequest, ) -> StopTrainingJobResponse: - """Stop a training job.""" + """Stops a training job""" return self._do_json( StopTrainingJobResponse, _ApiRequest( @@ -2605,6 +2914,20 @@ async def delete_chains_deployments( ), ) + async def delete_gateway_endpoints(self, *, endpoint_id: str) -> EndpointTombstone: + """Deletes a Gateway endpoint""" + return await self._do_json( + EndpointTombstone, + _ApiRequest( + method="DELETE", + path_fmt="/v1/gateway/endpoints/{}", + path_args=[endpoint_id], + body=None, + success_code=200, + error_codes=None, + ), + ) + async def delete_library_listings( self, *, user_defined_listing_id: str ) -> LibraryListingTombstone: @@ -2716,7 +3039,7 @@ async def delete_teams_secrets( async def delete_training_projects( self, *, training_project_id: str ) -> TrainingProjectTombstone: - """Delete a training project.""" + """Deletes a training project""" return await self._do_json( TrainingProjectTombstone, _ApiRequest( @@ -2732,7 +3055,7 @@ async def delete_training_projects( async def delete_training_projects_jobs( self, *, training_project_id: str, training_job_id: str ) -> TrainingJobTombstone: - """Delete a training job.""" + """Deletes a training job""" return await self._do_json( TrainingJobTombstone, _ApiRequest( @@ -2746,7 +3069,7 @@ async def delete_training_projects_jobs( ) async def get_api_keys(self) -> APIKeys: - """Lists the user's API keys (metadata only, no plain text keys)""" + """Lists API keys (metadata only, no plain text keys)""" return await self._do_json( APIKeys, _ApiRequest( @@ -2774,7 +3097,7 @@ async def get_billing_usage_summary(self) -> UsageSummary: ) async def get_blobs_credentials_model(self) -> GetBlobCredentialsResponse: - """Get blob credentials for models.""" + """Gets blob credentials for models""" return await self._do_json( GetBlobCredentialsResponse, _ApiRequest( @@ -2788,7 +3111,7 @@ async def get_blobs_credentials_model(self) -> GetBlobCredentialsResponse: ) async def get_blobs_credentials_train(self) -> GetBlobCredentialsResponse: - """Get blob credentials for training.""" + """Gets blob credentials for training""" return await self._do_json( GetBlobCredentialsResponse, _ApiRequest( @@ -2862,7 +3185,7 @@ async def get_chains_deployments_chain_deployment_id( async def get_chains_deployments_chainlets_logs( self, *, chain_id: str, chain_deployment_id: str, chainlet_id: str ) -> GetLogsResponse: - """Gets the logs for a chainlet within a chain deployment.""" + """Gets the logs for a chainlet within a chain deployment""" return await self._do_json( GetLogsResponse, _ApiRequest( @@ -2876,7 +3199,7 @@ async def get_chains_deployments_chainlets_logs( ) async def get_chains_environments(self, *, chain_id: str) -> Environments: - """Get all chain environments""" + """Gets all chain environments""" return await self._do_json( Environments, _ApiRequest( @@ -2892,7 +3215,7 @@ async def get_chains_environments(self, *, chain_id: str) -> Environments: async def get_chains_environments_env_name( self, *, chain_id: str, env_name: str ) -> ChainEnvironment: - """Get a chain environment's details""" + """Gets a chain environment's details""" return await self._do_json( ChainEnvironment, _ApiRequest( @@ -2905,8 +3228,66 @@ async def get_chains_environments_env_name( ), ) + async def get_environment_groups(self) -> EnvironmentGroups: + """Lists environment groups""" + return await self._do_json( + EnvironmentGroups, + _ApiRequest( + method="GET", + path_fmt="/v1/environment_groups", + path_args=[], + body=None, + success_code=200, + error_codes=None, + ), + ) + + async def get_environment_groups_env_name( + self, *, env_name: str + ) -> EnvironmentGroup: + """Gets an environment group by name""" + return await self._do_json( + EnvironmentGroup, + _ApiRequest( + method="GET", + path_fmt="/v1/environment_groups/{}", + path_args=[env_name], + body=None, + success_code=200, + error_codes=None, + ), + ) + + async def get_gateway_endpoints(self) -> EndpointsResponse: + """Lists Gateway endpoints""" + return await self._do_json( + EndpointsResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/gateway/endpoints", + path_args=[], + body=None, + success_code=200, + error_codes=None, + ), + ) + + async def get_gateway_endpoints_endpoint_id(self, *, endpoint_id: str) -> Endpoint: + """Gets a Gateway endpoint""" + return await self._do_json( + Endpoint, + _ApiRequest( + method="GET", + path_fmt="/v1/gateway/endpoints/{}", + path_args=[endpoint_id], + body=None, + success_code=200, + error_codes=None, + ), + ) + async def get_gateway_groups(self) -> GroupsResponse: - """List groups""" + """Lists groups""" return await self._do_json( GroupsResponse, _ApiRequest( @@ -2922,7 +3303,7 @@ async def get_gateway_groups(self) -> GroupsResponse: async def get_gateway_groups_api_keys( self, *, group_id: str ) -> KeysForGroupResponse: - """List API keys for a group""" + """Lists API keys for a group""" return await self._do_json( KeysForGroupResponse, _ApiRequest( @@ -2938,7 +3319,7 @@ async def get_gateway_groups_api_keys( async def get_gateway_groups_api_keys_api_key_prefix( self, *, group_id: str, api_key_prefix: str ) -> GatewayKeyInfo: - """Get an API key for a group""" + """Gets an API key for a group""" return await self._do_json( GatewayKeyInfo, _ApiRequest( @@ -2952,7 +3333,7 @@ async def get_gateway_groups_api_keys_api_key_prefix( ) async def get_gateway_groups_group_id(self, *, group_id: str) -> Group: - """Get a group""" + """Gets a group""" return await self._do_json( Group, _ApiRequest( @@ -2966,7 +3347,7 @@ async def get_gateway_groups_group_id(self, *, group_id: str) -> Group: ) async def get_instance_type_prices(self) -> InstanceTypePrices: - """Gets prices for available instance types.""" + """Gets prices for available instance types""" return await self._do_json( InstanceTypePrices, _ApiRequest( @@ -3056,7 +3437,7 @@ async def get_library_listings_versions_version_tag( ) async def get_loops_capabilities(self) -> GetLoopsCapabilitiesResponse: - """Get Loops server capabilities.""" + """Gets Loops server capabilities""" return await self._do_json( GetLoopsCapabilitiesResponse, _ApiRequest( @@ -3070,7 +3451,7 @@ async def get_loops_capabilities(self) -> GetLoopsCapabilitiesResponse: ) async def get_loops_checkpoints(self) -> ListLoopsCheckpointsResponse: - """List Loops checkpoints.""" + """Lists Loops checkpoints""" return await self._do_json( ListLoopsCheckpointsResponse, _ApiRequest( @@ -3086,7 +3467,7 @@ async def get_loops_checkpoints(self) -> ListLoopsCheckpointsResponse: async def get_loops_checkpoints_files( self, *, checkpoint_id: str ) -> LoopsCheckpointFilesResponse: - """Get Loops checkpoint files.""" + """Gets Loops checkpoint files""" return await self._do_json( LoopsCheckpointFilesResponse, _ApiRequest( @@ -3100,7 +3481,7 @@ async def get_loops_checkpoints_files( ) async def get_loops_deployments(self) -> ListLoopsDeploymentsResponse: - """List Loops deployments.""" + """Lists Loops deployments""" return await self._do_json( ListLoopsDeploymentsResponse, _ApiRequest( @@ -3116,7 +3497,7 @@ async def get_loops_deployments(self) -> ListLoopsDeploymentsResponse: async def get_loops_deployments_deployment_id( self, *, deployment_id: str ) -> GetLoopsDeploymentResponse: - """Get a Loops deployment.""" + """Gets a Loops deployment""" return await self._do_json( GetLoopsDeploymentResponse, _ApiRequest( @@ -3132,7 +3513,7 @@ async def get_loops_deployments_deployment_id( async def get_loops_deployments_logs( self, *, deployment_id: str ) -> GetLogsResponse: - """Get logs for a Loops trainer deployment.""" + """Gets logs for a Loops trainer deployment""" return await self._do_json( GetLogsResponse, _ApiRequest( @@ -3146,7 +3527,7 @@ async def get_loops_deployments_logs( ) async def get_loops_runs(self) -> ListLoopsRunsResponse: - """List Loops runs.""" + """Lists Loops runs""" return await self._do_json( ListLoopsRunsResponse, _ApiRequest( @@ -3160,7 +3541,7 @@ async def get_loops_runs(self) -> ListLoopsRunsResponse: ) async def get_loops_runs_run_id(self, *, run_id: str) -> GetLoopsRunResponse: - """Get a Loops run.""" + """Gets a Loops run""" return await self._do_json( GetLoopsRunResponse, _ApiRequest( @@ -3174,7 +3555,7 @@ async def get_loops_runs_run_id(self, *, run_id: str) -> GetLoopsRunResponse: ) async def get_loops_samplers(self) -> ListLoopsSamplersResponse: - """List Loops samplers.""" + """Lists Loops samplers""" return await self._do_json( ListLoopsSamplersResponse, _ApiRequest( @@ -3190,7 +3571,7 @@ async def get_loops_samplers(self) -> ListLoopsSamplersResponse: async def get_loops_samplers_sampler_id( self, *, sampler_id: str ) -> GetLoopsSamplerResponse: - """Get a Loops sampler.""" + """Gets a Loops sampler""" return await self._do_json( GetLoopsSamplerResponse, _ApiRequest( @@ -3204,7 +3585,7 @@ async def get_loops_samplers_sampler_id( ) async def get_loops_sessions(self, *, session_id: str) -> GetLoopsSessionResponse: - """Get a Loops session.""" + """Gets a Loops session""" return await self._do_json( GetLoopsSessionResponse, _ApiRequest( @@ -3217,8 +3598,50 @@ async def get_loops_sessions(self, *, session_id: str) -> GetLoopsSessionRespons ), ) + async def get_loops_user_config(self) -> GetLoopsUserConfigResponse: + """Gets the caller's Loops user config""" + return await self._do_json( + GetLoopsUserConfigResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/loops/user_config", + path_args=[], + body=None, + success_code=200, + error_codes=None, + ), + ) + + async def get_model_apis(self) -> ModelAPIsResponse: + """Lists Model APIs""" + return await self._do_json( + ModelAPIsResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/model_apis", + path_args=[], + body=None, + success_code=200, + error_codes=None, + ), + ) + + async def get_model_apis_model_api_name(self, *, model_api_name: str) -> ModelAPI: + """Gets a Model API""" + return await self._do_json( + ModelAPI, + _ApiRequest( + method="GET", + path_fmt="/v1/model_apis/{}", + path_args=[model_api_name], + body=None, + success_code=200, + error_codes=None, + ), + ) + async def get_model_apis_snapshots(self) -> ModelWeightSnapshot: - """Get the latest model weight snapshot""" + """Gets the latest model weight snapshot""" return await self._do_json( ModelWeightSnapshot, _ApiRequest( @@ -3234,7 +3657,7 @@ async def get_model_apis_snapshots(self) -> ModelWeightSnapshot: async def get_model_apis_snapshots_model_id( self, *, model_id: str ) -> ModelWeightSnapshot: - """Get the latest model weight snapshot""" + """Gets the latest model weight snapshot""" return await self._do_json( ModelWeightSnapshot, _ApiRequest( @@ -3340,7 +3763,7 @@ async def get_models_deployments_download( async def get_models_deployments_logs( self, *, model_id: str, deployment_id: str ) -> GetLogsResponse: - """Gets the logs for a model deployment.""" + """Gets the logs for a model deployment""" return await self._do_json( GetLogsResponse, _ApiRequest( @@ -3353,6 +3776,38 @@ async def get_models_deployments_logs( ), ) + async def get_models_deployments_metrics( + self, *, model_id: str, deployment_id: str + ) -> GetModelMetricsResponse: + """Gets the metrics for a model deployment""" + return await self._do_json( + GetModelMetricsResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/models/{}/deployments/{}/metrics", + path_args=[model_id, deployment_id], + body=None, + success_code=200, + error_codes=None, + ), + ) + + async def get_models_deployments_patches_state( + self, *, model_id: str, deployment_id: str + ) -> GetDeploymentPatchesStateResponse: + """Gets a development deployment's patch state""" + return await self._do_json( + GetDeploymentPatchesStateResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/models/{}/deployments/{}/patches/state", + path_args=[model_id, deployment_id], + body=None, + success_code=200, + error_codes=None, + ), + ) + async def get_models_deployments_production(self, *, model_id: str) -> Deployment: """Gets a model's production deployment""" return await self._do_json( @@ -3368,7 +3823,7 @@ async def get_models_deployments_production(self, *, model_id: str) -> Deploymen ) async def get_models_environments(self, *, model_id: str) -> Environments: - """Get all environments""" + """Gets all environments""" return await self._do_json( Environments, _ApiRequest( @@ -3384,7 +3839,7 @@ async def get_models_environments(self, *, model_id: str) -> Environments: async def get_models_environments_env_name( self, *, model_id: str, env_name: str ) -> Environment: - """Get an environment's details""" + """Gets an environment's details""" return await self._do_json( Environment, _ApiRequest( @@ -3397,6 +3852,38 @@ async def get_models_environments_env_name( ), ) + async def get_models_environments_logs( + self, *, model_id: str, env_name: str + ) -> GetLogsResponse: + """Gets the logs for a model environment""" + return await self._do_json( + GetLogsResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/models/{}/environments/{}/logs", + path_args=[model_id, env_name], + body=None, + success_code=200, + error_codes=None, + ), + ) + + async def get_models_environments_metrics( + self, *, model_id: str, env_name: str + ) -> GetModelMetricsResponse: + """Gets the metrics for a model environment.""" + return await self._do_json( + GetModelMetricsResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/models/{}/environments/{}/metrics", + path_args=[model_id, env_name], + body=None, + success_code=200, + error_codes=None, + ), + ) + async def get_models_model_id(self, *, model_id: str) -> Model: """Gets a model by ID""" return await self._do_json( @@ -3439,6 +3926,36 @@ async def get_teams(self) -> Teams: ), ) + async def get_teams_environment_groups(self, *, team_id: str) -> EnvironmentGroups: + """Lists environment groups""" + return await self._do_json( + EnvironmentGroups, + _ApiRequest( + method="GET", + path_fmt="/v1/teams/{}/environment_groups", + path_args=[team_id], + body=None, + success_code=200, + error_codes=None, + ), + ) + + async def get_teams_environment_groups_env_name( + self, *, team_id: str, env_name: str + ) -> EnvironmentGroup: + """Gets an environment group by name""" + return await self._do_json( + EnvironmentGroup, + _ApiRequest( + method="GET", + path_fmt="/v1/teams/{}/environment_groups/{}", + path_args=[team_id, env_name], + body=None, + success_code=200, + error_codes=None, + ), + ) + async def get_teams_models(self, *, team_id: str) -> Models: """Gets all models""" return await self._do_json( @@ -3467,46 +3984,44 @@ async def get_teams_secrets(self, *, team_id: str) -> Secrets: ), ) - async def get_trainer_sessions_trainers_checkpoints( - self, *, session_id: str, trainer_id: str - ) -> GetTrainerServerCheckpointsResponse: - """List trainer server checkpoints.""" + async def get_teams_team_id(self, *, team_id: str) -> Team: + """Gets a team by ID""" return await self._do_json( - GetTrainerServerCheckpointsResponse, + Team, _ApiRequest( method="GET", - path_fmt="/v1/trainer_sessions/{}/trainers/{}/checkpoints", - path_args=[session_id, trainer_id], + path_fmt="/v1/teams/{}", + path_args=[team_id], body=None, success_code=200, error_codes=None, ), ) - async def get_trainer_sessions_trainers_checkpoints_files( - self, *, session_id: str, trainer_id: str, checkpoint_id: str - ) -> GetTrainerServerCheckpointFilesResponse: - """Get trainer server checkpoint files.""" + async def get_training_capacity(self) -> GetTrainingGpuCapacityResponse: + """Gets training GPU capacity""" return await self._do_json( - GetTrainerServerCheckpointFilesResponse, + GetTrainingGpuCapacityResponse, _ApiRequest( method="GET", - path_fmt="/v1/trainer_sessions/{}/trainers/{}/checkpoints/{}/files", - path_args=[session_id, trainer_id, checkpoint_id], + path_fmt="/v1/training/capacity", + path_args=[], body=None, success_code=200, error_codes=None, ), ) - async def get_training_capacity(self) -> GetTrainingGpuCapacityResponse: - """Get training GPU capacity.""" + async def get_training_jobs_queue_context( + self, *, training_job_id: str + ) -> GetTrainingJobQueueContextResponse: + """Reconstructs queue context for a training job""" return await self._do_json( - GetTrainingGpuCapacityResponse, + GetTrainingJobQueueContextResponse, _ApiRequest( method="GET", - path_fmt="/v1/training/capacity", - path_args=[], + path_fmt="/v1/training/jobs/{}/queue_context", + path_args=[training_job_id], body=None, success_code=200, error_codes=None, @@ -3514,7 +4029,7 @@ async def get_training_capacity(self) -> GetTrainingGpuCapacityResponse: ) async def get_training_projects(self) -> ListTrainingProjectsResponse: - """List training projects.""" + """Lists training projects""" return await self._do_json( ListTrainingProjectsResponse, _ApiRequest( @@ -3530,7 +4045,7 @@ async def get_training_projects(self) -> ListTrainingProjectsResponse: async def get_training_projects_cache_summary( self, *, training_project_id: str ) -> GetCacheSummaryResponse: - """Get training project cache summary.""" + """Gets training project cache summary""" return await self._do_json( GetCacheSummaryResponse, _ApiRequest( @@ -3546,7 +4061,7 @@ async def get_training_projects_cache_summary( async def get_training_projects_jobs( self, *, training_project_id: str ) -> ListTrainingJobsResponse: - """List training jobs.""" + """Lists training jobs""" return await self._do_json( ListTrainingJobsResponse, _ApiRequest( @@ -3562,7 +4077,7 @@ async def get_training_projects_jobs( async def get_training_projects_jobs_auth_codes( self, *, training_project_id: str, training_job_id: str ) -> GetAuthCodesResponse: - """Get auth codes for a training job.""" + """Gets auth codes for a training job""" return await self._do_json( GetAuthCodesResponse, _ApiRequest( @@ -3578,7 +4093,7 @@ async def get_training_projects_jobs_auth_codes( async def get_training_projects_jobs_checkpoint_files( self, *, training_project_id: str, training_job_id: str ) -> GetTrainingJobCheckpointFilesResponse: - """Get training job checkpoint files.""" + """Gets training job checkpoint files""" return await self._do_json( GetTrainingJobCheckpointFilesResponse, _ApiRequest( @@ -3594,7 +4109,7 @@ async def get_training_projects_jobs_checkpoint_files( async def get_training_projects_jobs_checkpoints( self, *, training_project_id: str, training_job_id: str ) -> GetTrainingJobCheckpointsResponse: - """Get training job checkpoints.""" + """Gets training job checkpoints""" return await self._do_json( GetTrainingJobCheckpointsResponse, _ApiRequest( @@ -3610,7 +4125,7 @@ async def get_training_projects_jobs_checkpoints( async def get_training_projects_jobs_download( self, *, training_project_id: str, training_job_id: str ) -> DownloadTrainingJobResponse: - """Get the uploaded training job as a S3 Artifact""" + """Gets presigned URLs for a training job's artifacts""" return await self._do_json( DownloadTrainingJobResponse, _ApiRequest( @@ -3626,7 +4141,7 @@ async def get_training_projects_jobs_download( async def get_training_projects_jobs_logs( self, *, training_project_id: str, training_job_id: str ) -> GetLogsResponse: - """Get the logs for a training job.""" + """Gets the logs for a training job""" return await self._do_json( GetLogsResponse, _ApiRequest( @@ -3642,7 +4157,7 @@ async def get_training_projects_jobs_logs( async def get_training_projects_jobs_metrics( self, *, training_project_id: str, training_job_id: str ) -> GetTrainingJobMetricsResponse: - """Get the metrics for a training job.""" + """Gets the metrics for a training job""" return await self._do_json( GetTrainingJobMetricsResponse, _ApiRequest( @@ -3658,7 +4173,7 @@ async def get_training_projects_jobs_metrics( async def get_training_projects_jobs_training_job_id( self, *, training_project_id: str, training_job_id: str ) -> GetTrainingJobResponse: - """Get a training job.""" + """Gets a training job""" return await self._do_json( GetTrainingJobResponse, _ApiRequest( @@ -3674,7 +4189,7 @@ async def get_training_projects_jobs_training_job_id( async def get_training_projects_training_project_id( self, *, training_project_id: str ) -> GetTrainingProjectResponse: - """Get a training project.""" + """Gets a training project""" return await self._do_json( GetTrainingProjectResponse, _ApiRequest( @@ -3687,7 +4202,35 @@ async def get_training_projects_training_project_id( ), ) - async def get_users(self, *, user_id: str) -> UserInfo: + async def get_users(self) -> UsersResponse: + """Lists users in the workspace""" + return await self._do_json( + UsersResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/users", + path_args=[], + body=None, + success_code=200, + error_codes=None, + ), + ) + + async def get_users_me(self) -> UserInfo: + """Gets the authenticated user""" + return await self._do_json( + UserInfo, + _ApiRequest( + method="GET", + path_fmt="/v1/users/me", + path_args=[], + body=None, + success_code=200, + error_codes=None, + ), + ) + + async def get_users_user_id(self, *, user_id: str) -> UserInfo: """Gets a user by ID""" return await self._do_json( UserInfo, @@ -3704,7 +4247,7 @@ async def get_users(self, *, user_id: str) -> UserInfo: async def patch_chains_environments( self, *, chain_id: str, env_name: str, body: UpdateChainEnvironmentRequest ) -> UpdateChainEnvironmentResponse: - """Update a chain environment's settings""" + """Updates a chain environment's settings""" return await self._do_json( UpdateChainEnvironmentResponse, _ApiRequest( @@ -3724,7 +4267,7 @@ async def patch_chains_environments_chainlet_settings_autoscaling_settings( env_name: str, body: UpdateChainletEnvironmentAutoscalingSettingsRequest, ) -> UpdateAutoscalingSettingsResponse: - """Update a chainlet environment's autoscaling settings""" + """Updates a chainlet environment's autoscaling settings""" return await self._do_json( UpdateAutoscalingSettingsResponse, _ApiRequest( @@ -3737,10 +4280,42 @@ async def patch_chains_environments_chainlet_settings_autoscaling_settings( ), ) + async def patch_environment_groups( + self, *, env_name: str, body: UpdateEnvironmentGroupRequest + ) -> EnvironmentGroup: + """Updates an environment group's restriction settings""" + return await self._do_json( + EnvironmentGroup, + _ApiRequest( + method="PATCH", + path_fmt="/v1/environment_groups/{}", + path_args=[env_name], + body=body, + success_code=200, + error_codes=None, + ), + ) + + async def patch_gateway_endpoints( + self, *, endpoint_id: str, body: UpdateEndpointRequest + ) -> Endpoint: + """Updates a Gateway endpoint""" + return await self._do_json( + Endpoint, + _ApiRequest( + method="PATCH", + path_fmt="/v1/gateway/endpoints/{}", + path_args=[endpoint_id], + body=body, + success_code=200, + error_codes=None, + ), + ) + async def patch_gateway_groups( self, *, group_id: str, body: UpdateGroupRequest ) -> Group: - """Update a group""" + """Updates a group""" return await self._do_json( Group, _ApiRequest( @@ -3789,6 +4364,22 @@ async def patch_library_listings_versions( ), ) + async def patch_loops_user_config( + self, *, body: PatchLoopsUserConfigRequest + ) -> PatchLoopsUserConfigResponse: + """Patches the caller's Loops user config""" + return await self._do_json( + PatchLoopsUserConfigResponse, + _ApiRequest( + method="PATCH", + path_fmt="/v1/loops/user_config", + path_args=[], + body=body, + success_code=200, + error_codes=None, + ), + ) + async def patch_models_deployments_autoscaling_settings( self, *, model_id: str, deployment_id: str, body: UpdateAutoscalingSettings ) -> UpdateAutoscalingSettingsResponse: @@ -3840,7 +4431,7 @@ async def patch_models_deployments_production_autoscaling_settings( async def patch_models_environments( self, *, model_id: str, env_name: str, body: UpdateEnvironmentRequest ) -> UpdateAutoscalingSettingsResponse: - """Update an environment's settings""" + """Updates an environment's settings""" return await self._do_json( UpdateAutoscalingSettingsResponse, _ApiRequest( @@ -3853,6 +4444,58 @@ async def patch_models_environments( ), ) + async def patch_teams_environment_groups( + self, *, team_id: str, env_name: str, body: UpdateEnvironmentGroupRequest + ) -> EnvironmentGroup: + """Updates an environment group's restriction settings""" + return await self._do_json( + EnvironmentGroup, + _ApiRequest( + method="PATCH", + path_fmt="/v1/teams/{}/environment_groups/{}", + path_args=[team_id, env_name], + body=body, + success_code=200, + error_codes=None, + ), + ) + + async def patch_training_capacity( + self, *, body: PatchTeamTrainingGpuCapacityRequest + ) -> PatchTeamTrainingGpuCapacityResponse: + """Sets a team's training GPU capacity""" + return await self._do_json( + PatchTeamTrainingGpuCapacityResponse, + _ApiRequest( + method="PATCH", + path_fmt="/v1/training/capacity", + path_args=[], + body=body, + success_code=200, + error_codes=None, + ), + ) + + async def patch_training_projects_jobs( + self, + *, + training_project_id: str, + training_job_id: str, + body: UpdateTrainingJobRequest, + ) -> UpdateTrainingJobResponse: + """Updates a training job""" + return await self._do_json( + UpdateTrainingJobResponse, + _ApiRequest( + method="PATCH", + path_fmt="/v1/training_projects/{}/jobs/{}", + path_args=[training_project_id, training_job_id], + body=body, + success_code=200, + error_codes=None, + ), + ) + async def patch_training_projects_jobs_interactive_sessions( self, *, @@ -3861,7 +4504,7 @@ async def patch_training_projects_jobs_interactive_sessions( session_id: str, body: PatchInteractiveSessionRequest, ) -> PatchInteractiveSessionResponse: - """Patch an interactive session.""" + """Patches an interactive session""" return await self._do_json( PatchInteractiveSessionResponse, _ApiRequest( @@ -3907,7 +4550,7 @@ async def post_chains_deployments_deactivate( async def post_chains_environments( self, *, chain_id: str, body: CreateChainEnvironmentRequest ) -> ChainEnvironment: - """Create a chain environment""" + """Creates a chain environment""" return await self._do_json( ChainEnvironment, _ApiRequest( @@ -3927,7 +4570,7 @@ async def post_chains_environments_chainlet_settings_instance_types_update( env_name: str, body: UpdateChainletEnvironmentInstanceTypeRequest, ) -> UpdateChainletEnvironmentInstanceTypeResponse: - """Update a chainlet environment's instance type settings.""" + """Updates a chainlet environment's instance type settings""" return await self._do_json( UpdateChainletEnvironmentInstanceTypeResponse, _ApiRequest( @@ -3956,8 +4599,22 @@ async def post_chains_environments_promote( ), ) + async def post_gateway_endpoints(self, *, body: CreateEndpointRequest) -> Endpoint: + """Creates a Gateway endpoint""" + return await self._do_json( + Endpoint, + _ApiRequest( + method="POST", + path_fmt="/v1/gateway/endpoints", + path_args=[], + body=body, + success_code=200, + error_codes=None, + ), + ) + async def post_gateway_groups(self, *, body: CreateGroupRequest) -> Group: - """Create a group""" + """Creates a group""" return await self._do_json( Group, _ApiRequest( @@ -3973,7 +4630,7 @@ async def post_gateway_groups(self, *, body: CreateGroupRequest) -> Group: async def post_gateway_groups_api_keys( self, *, group_id: str, body: CreateApiKeyForGroupRequest ) -> CreateApiKeyForGroupResponse: - """Create an API key for a group""" + """Creates an API key for a group""" return await self._do_json( CreateApiKeyForGroupResponse, _ApiRequest( @@ -3989,7 +4646,7 @@ async def post_gateway_groups_api_keys( async def post_gateway_groups_api_keys_register( self, *, group_id: str, body: RegisterAPIKeyRequest ) -> RegisterAPIKeyResponse: - """Register an API key for a group""" + """Registers an API key for a group""" return await self._do_json( RegisterAPIKeyResponse, _ApiRequest( @@ -4035,7 +4692,7 @@ async def post_library_listings_versions( ) async def post_llm_models(self, *, body: CreateLLMModelRequest) -> LLMModelHandle: - """Creates a new BIS LLM deployment""" + """Creates a new BIS-LLM deployment""" return await self._do_json( LLMModelHandle, _ApiRequest( @@ -4051,7 +4708,7 @@ async def post_llm_models(self, *, body: CreateLLMModelRequest) -> LLMModelHandl async def post_llm_models_deployments( self, *, model_id: str, body: CreateLLMModelVersionRequest ) -> LLMModelHandle: - """Creates a new BIS LLM deployment version""" + """Creates a new BIS-LLM deployment version""" return await self._do_json( LLMModelHandle, _ApiRequest( @@ -4067,7 +4724,7 @@ async def post_llm_models_deployments( async def post_loops_checkpoints_validate( self, *, body: ValidateLoopsCheckpointRequest ) -> ValidateLoopsCheckpointResponse: - """Validate a Loops checkpoint bt:// URI.""" + """Validates a Loops checkpoint bt:// URI""" return await self._do_json( ValidateLoopsCheckpointResponse, _ApiRequest( @@ -4083,7 +4740,7 @@ async def post_loops_checkpoints_validate( async def post_loops_deployments_deactivate( self, *, deployment_id: str ) -> DeactivateLoopsDeploymentResponse: - """Deactivate a Loops deployment.""" + """Deactivates a Loops deployment""" return await self._do_json( DeactivateLoopsDeploymentResponse, _ApiRequest( @@ -4099,7 +4756,7 @@ async def post_loops_deployments_deactivate( async def post_loops_deployments_metrics( self, *, deployment_id: str, body: GetLoopsDeploymentMetricsRequest ) -> GetLoopsDeploymentMetricsResponse: - """Get metrics for a Loops trainer deployment.""" + """Gets metrics for a Loops trainer deployment""" return await self._do_json( GetLoopsDeploymentMetricsResponse, _ApiRequest( @@ -4115,7 +4772,7 @@ async def post_loops_deployments_metrics( async def post_loops_runs( self, *, body: CreateLoopsRunRequest ) -> CreateLoopsRunResponse: - """Create a Loops run.""" + """Creates a Loops run""" return await self._do_json( CreateLoopsRunResponse, _ApiRequest( @@ -4131,7 +4788,7 @@ async def post_loops_runs( async def post_loops_samplers( self, *, body: CreateLoopsSamplerRequest ) -> CreateLoopsSamplerResponse: - """Create a Loops sampler.""" + """Creates a Loops sampler""" return await self._do_json( CreateLoopsSamplerResponse, _ApiRequest( @@ -4144,17 +4801,15 @@ async def post_loops_samplers( ), ) - async def post_loops_sessions( - self, *, body: CreateLoopsSessionRequest - ) -> CreateLoopsSessionResponse: - """Create a Loops session.""" + async def post_loops_sessions(self) -> CreateLoopsSessionResponse: + """Creates a Loops session""" return await self._do_json( CreateLoopsSessionResponse, _ApiRequest( method="POST", path_fmt="/v1/loops/sessions", path_args=[], - body=body, + body=None, success_code=200, error_codes=None, ), @@ -4163,7 +4818,7 @@ async def post_loops_sessions( async def post_model_apis_snapshots( self, *, body: CreateModelWeightSnapshotRequest ) -> ModelWeightSnapshot: - """Create a model weight snapshot""" + """Creates a model weight snapshot""" return await self._do_json( ModelWeightSnapshot, _ApiRequest( @@ -4179,7 +4834,7 @@ async def post_model_apis_snapshots( async def post_model_apis_snapshots_model_id( self, *, model_id: str, body: CreateModelWeightSnapshotRequest ) -> ModelWeightSnapshot: - """Create a model weight snapshot""" + """Creates a model weight snapshot""" return await self._do_json( ModelWeightSnapshot, _ApiRequest( @@ -4321,7 +4976,7 @@ async def post_models_deployments_development_retry( async def post_models_deployments_logs( self, *, model_id: str, deployment_id: str, body: GetDeploymentLogsRequest ) -> GetLogsResponse: - """Gets the logs for a model deployment (deprecated; use GET).""" + """Gets the logs for a model deployment (deprecated; use GET)""" return await self._do_json( GetLogsResponse, _ApiRequest( @@ -4334,6 +4989,38 @@ async def post_models_deployments_logs( ), ) + async def post_models_deployments_patches( + self, *, model_id: str, deployment_id: str, body: CreateDeploymentPatchRequest + ) -> CreateDeploymentPatchResponse: + """Stages a patch against a development deployment""" + return await self._do_json( + CreateDeploymentPatchResponse, + _ApiRequest( + method="POST", + path_fmt="/v1/models/{}/deployments/{}/patches", + path_args=[model_id, deployment_id], + body=body, + success_code=200, + error_codes=None, + ), + ) + + async def post_models_deployments_patches_sync( + self, *, model_id: str, deployment_id: str, body: SyncDeploymentPatchesRequest + ) -> SyncDeploymentPatchesResponse: + """Syncs staged patches to a development deployment""" + return await self._do_json( + SyncDeploymentPatchesResponse, + _ApiRequest( + method="POST", + path_fmt="/v1/models/{}/deployments/{}/patches/sync", + path_args=[model_id, deployment_id], + body=body, + success_code=200, + error_codes=None, + ), + ) + async def post_models_deployments_production_activate( self, *, model_id: str ) -> ActivateResponse: @@ -4417,7 +5104,7 @@ async def post_models_deployments_retry( async def post_models_deployments_ssh_sign( self, *, model_id: str, deployment_id: str, body: SignSSHCertificateRequest ) -> SignSSHCertificateResponse: - """Sign an SSH certificate for an inference model.""" + """Signs an SSH certificate for an inference model""" return await self._do_json( SignSSHCertificateResponse, _ApiRequest( @@ -4433,7 +5120,7 @@ async def post_models_deployments_ssh_sign( async def post_models_environments( self, *, model_id: str, body: CreateEnvironmentRequest ) -> Environment: - """Create an environment""" + """Creates an environment""" return await self._do_json( Environment, _ApiRequest( @@ -4623,7 +5310,7 @@ async def post_teams_api_keys( async def post_teams_llm_models( self, *, team_id: str, body: CreateLLMModelRequest ) -> LLMModelHandle: - """Creates a new BIS LLM deployment""" + """Creates a new BIS-LLM deployment""" return await self._do_json( LLMModelHandle, _ApiRequest( @@ -4671,7 +5358,7 @@ async def post_teams_secrets( async def post_teams_training_projects( self, *, team_id: str, body: UpsertTrainingProjectRequest ) -> UpsertTrainingProjectResponse: - """Upsert a training project in a specific team.""" + """Upserts a training project in a specific team""" return await self._do_json( UpsertTrainingProjectResponse, _ApiRequest( @@ -4684,90 +5371,10 @@ async def post_teams_training_projects( ), ) - async def post_trainer_sessions( - self, *, body: CreateTrainerSessionRequest - ) -> CreateTrainerSessionResponse: - """Create a trainer session.""" - return await self._do_json( - CreateTrainerSessionResponse, - _ApiRequest( - method="POST", - path_fmt="/v1/trainer_sessions", - path_args=[], - body=body, - success_code=200, - error_codes=None, - ), - ) - - async def post_trainer_sessions_samplers( - self, *, session_id: str, body: CreateSamplingServerRequest - ) -> CreateSamplingServerResponse: - """Create a sampling server.""" - return await self._do_json( - CreateSamplingServerResponse, - _ApiRequest( - method="POST", - path_fmt="/v1/trainer_sessions/{}/samplers", - path_args=[session_id], - body=body, - success_code=200, - error_codes=None, - ), - ) - - async def post_trainer_sessions_trainers( - self, *, session_id: str, body: CreateTrainerServerRequest - ) -> CreateTrainerServerResponse: - """Create a trainer server.""" - return await self._do_json( - CreateTrainerServerResponse, - _ApiRequest( - method="POST", - path_fmt="/v1/trainer_sessions/{}/trainers", - path_args=[session_id], - body=body, - success_code=200, - error_codes=None, - ), - ) - - async def post_trainers_checkpoints_search( - self, *, body: CheckpointSearchRequest - ) -> CheckpointSearchResponse: - """Look up trainer checkpoint info by bt:// URI.""" - return await self._do_json( - CheckpointSearchResponse, - _ApiRequest( - method="POST", - path_fmt="/v1/trainers/checkpoints/search", - path_args=[], - body=body, - success_code=200, - error_codes=None, - ), - ) - - async def post_trainers_search( - self, *, body: SearchTrainersRequest - ) -> SearchTrainersResponse: - """Search trainers.""" - return await self._do_json( - SearchTrainersResponse, - _ApiRequest( - method="POST", - path_fmt="/v1/trainers/search", - path_args=[], - body=body, - success_code=200, - error_codes=None, - ), - ) - async def post_training_jobs_search( self, *, body: SearchTrainingJobsRequest ) -> SearchTrainingJobsResponse: - """Search training jobs.""" + """Searches training jobs""" return await self._do_json( SearchTrainingJobsResponse, _ApiRequest( @@ -4783,7 +5390,7 @@ async def post_training_jobs_search( async def post_training_projects( self, *, body: UpsertTrainingProjectRequest ) -> UpsertTrainingProjectResponse: - """Upsert a training project.""" + """Upserts a training project""" return await self._do_json( UpsertTrainingProjectResponse, _ApiRequest( @@ -4799,7 +5406,7 @@ async def post_training_projects( async def post_training_projects_jobs( self, *, training_project_id: str, body: CreateTrainingJobRequest ) -> CreateTrainingJobResponse: - """Create a training job.""" + """Creates a training job""" return await self._do_json( CreateTrainingJobResponse, _ApiRequest( @@ -4819,7 +5426,7 @@ async def post_training_projects_jobs_logs( training_job_id: str, body: GetTrainingJobLogsRequest, ) -> GetLogsResponse: - """Get the logs for a training job (deprecated; use GET).""" + """Gets the logs for a training job (deprecated; use GET)""" return await self._do_json( GetLogsResponse, _ApiRequest( @@ -4839,7 +5446,7 @@ async def post_training_projects_jobs_metrics( training_job_id: str, body: GetTrainingJobMetricsRequest, ) -> GetTrainingJobMetricsResponse: - """Get the metrics for a training job (deprecated; use GET).""" + """Gets the metrics for a training job (deprecated; use GET)""" return await self._do_json( GetTrainingJobMetricsResponse, _ApiRequest( @@ -4855,7 +5462,7 @@ async def post_training_projects_jobs_metrics( async def post_training_projects_jobs_recreate( self, *, training_project_id: str, training_job_id: str ) -> RecreateTrainingJobResponse: - """Recreate a training job""" + """Recreates a training job""" return await self._do_json( RecreateTrainingJobResponse, _ApiRequest( @@ -4875,7 +5482,7 @@ async def post_training_projects_jobs_ssh_sign( training_job_id: str, body: SignSSHCertificateRequest, ) -> SignSSHCertificateResponse: - """Sign an SSH certificate for a training job.""" + """Signs an SSH certificate for a training job""" return await self._do_json( SignSSHCertificateResponse, _ApiRequest( @@ -4895,7 +5502,7 @@ async def post_training_projects_jobs_stop( training_job_id: str, body: StopTrainingJobRequest, ) -> StopTrainingJobResponse: - """Stop a training job.""" + """Stops a training job""" return await self._do_json( StopTrainingJobResponse, _ApiRequest( diff --git a/baseten/client/managementapi/_models.py b/baseten/client/managementapi/_models.py index cfab263..0950e23 100644 --- a/baseten/client/managementapi/_models.py +++ b/baseten/client/managementapi/_models.py @@ -19,6 +19,11 @@ class CheckpointSyncStatus(Enum): COMPLETED = "COMPLETED" +class V1AvailabilityModel(Enum): + dedicated = "dedicated" + spot = "spot" + + class BasetenLatestCheckpointConfig(BaseModel): project_name: Annotated[ str | None, @@ -155,31 +160,31 @@ class GitInfo(BaseModel): has_uncommitted_changes: Annotated[bool, Field(title="Has Uncommitted Changes")] -class Checkpoints( - RootModel[BasetenLatestCheckpointConfig | BasetenNamedCheckpointConfig] -): - root: Annotated[ - BasetenLatestCheckpointConfig | BasetenNamedCheckpointConfig, - Field(discriminator="typ"), - ] +class Target(Enum): + trainer = "trainer" + sampler = "sampler" -class LoadCheckpointConfig(BaseModel): - enabled: Annotated[ - bool | None, - Field(description="Whether checkpoint loading is enabled", title="Enabled"), - ] = False - download_folder: Annotated[ - str | None, +class LoopsCheckpointConfig(BaseModel): + run_id: Annotated[ + str, Field( - description="Folder where checkpoints will be downloaded", - title="Download Folder", + description="ID of the Loops run to load the checkpoint from", + title="Run Id", ), - ] = "/tmp/loaded_checkpoints" - checkpoints: Annotated[ - list[Checkpoints] | None, - Field(description="List of checkpoint configurations", title="Checkpoints"), - ] = None + ] + checkpoint_name: Annotated[ + str, + Field(description="Name of the checkpoint to load", title="Checkpoint Name"), + ] + target: Annotated[ + Target | None, + Field( + description="Which checkpoint target to load: 'trainer' (full training state) or 'sampler' (inference weights)", + title="Target", + ), + ] = Target.trainer + typ: Annotated[Literal["loops_checkpoint"], Field(title="Typ")] = "loops_checkpoint" class TrussUserEnv(BaseModel): @@ -266,7 +271,24 @@ class ResourceKind(Enum): CHAINLET = "CHAINLET" +class GatewayProvider(Enum): + ANTHROPIC = "ANTHROPIC" + OPENAI = "OPENAI" + BASETEN = "BASETEN" + BASETEN_MODEL_API = "BASETEN_MODEL_API" + VERTEX = "VERTEX" + OPENAI_COMPATIBLE = "OPENAI_COMPATIBLE" + + class Secret(BaseModel): + id: Annotated[ + str, + Field( + description="Stable identifier for the secret. Unchanged across rotation.", + examples=["3kZ9xqd"], + title="Id", + ), + ] created_at: Annotated[ AwareDatetime, Field( @@ -308,6 +330,60 @@ class SecretTombstone(BaseModel): name: Annotated[str, Field(description="Name of the deleted secret", title="Name")] +class EnvironmentGroupUser(BaseModel): + user_id: Annotated[ + str, Field(description="Unique identifier for the user.", title="User Id") + ] + email: Annotated[ + str | None, Field(description="Email address of the user.", title="Email") + ] = None + name: Annotated[ + str | None, Field(description="Display name of the user.", title="Name") + ] = None + + +class PaginationResponse(BaseModel): + has_more: Annotated[ + bool, + Field( + description="Whether more items exist after this page.", title="Has More" + ), + ] + cursor: Annotated[ + str | None, + Field( + description="Opaque cursor to pass into the next request. Null when there is no next page.", + title="Cursor", + ), + ] = None + + +class UpdateEnvironmentGroupManageAccess(BaseModel): + is_restricted: Annotated[ + bool, + Field( + description="Whether to restrict this environment to a specific set of users.", + title="Is Restricted", + ), + ] + user_ids: Annotated[ + list[str] | None, + Field( + description="IDs of users granted manage access while restricted. Only meaningful when is_restricted is true.", + title="User Ids", + ), + ] = None + + +class UpdateEnvironmentGroupRequest(BaseModel): + manage_access: Annotated[ + UpdateEnvironmentGroupManageAccess | None, + Field( + description="Manage-access settings to apply. Omit to leave manage access unchanged." + ), + ] = None + + class Team(BaseModel): id: Annotated[str, Field(description="Unique identifier of the team", title="Id")] name: Annotated[str, Field(description="Name of the team", title="Name")] @@ -331,6 +407,16 @@ class Teams(BaseModel): teams: Annotated[list[Team], Field(description="A list of teams", title="Teams")] +class TeamsRequest(BaseModel): + name: Annotated[ + str | None, + Field( + description="When set, returns only the team with this exact name, if any.", + title="Name", + ), + ] = None + + class InstanceType(BaseModel): id: Annotated[ str, Field(description="Identifier string for the instance type", title="Id") @@ -372,6 +458,56 @@ class InstanceTypes(BaseModel): instance_types: Annotated[list[InstanceType], Field(title="Instance Types")] +class LoopsUserConfig(BaseModel): + trainer_accelerator_priority: Annotated[ + list[str] | None, + Field( + description="Ordered allowlist of GPU types for your Loops trainer deployments, highest priority first. Intersected with the org-level allowlist (org acts as a ceiling). Null means 'inherit the org-level allowlist'.", + examples=[["H100", "H200"]], + title="Trainer Accelerator Priority", + ), + ] + sampler_accelerator_priority: Annotated[ + list[str] | None, + Field( + description="Ordered allowlist of GPU types for your Loops sampler deployments, highest priority first. Intersected with the org-level allowlist (org acts as a ceiling). Null means 'inherit the org-level allowlist'.", + examples=[["H100", "H200"]], + title="Sampler Accelerator Priority", + ), + ] + + +class GetLoopsUserConfigResponse(BaseModel): + user_config: Annotated[ + LoopsUserConfig, Field(description="The caller's Loops user config.") + ] + + +class PatchLoopsUserConfigRequest(BaseModel): + trainer_accelerator_priority: Annotated[ + list[str] | None, + Field( + description="Ordered list of GPU types for trainer deployments, highest priority first. Send a list to set; send null to clear (inherit org allowlist); omit to leave unchanged. Empty list is rejected.", + examples=[["H100", "H200"]], + title="Trainer Accelerator Priority", + ), + ] = None + sampler_accelerator_priority: Annotated[ + list[str] | None, + Field( + description="Ordered list of GPU types for sampler deployments, highest priority first. Send a list to set; send null to clear (inherit org allowlist); omit to leave unchanged. Empty list is rejected.", + examples=[["H100", "H200"]], + title="Sampler Accelerator Priority", + ), + ] = None + + +class PatchLoopsUserConfigResponse(BaseModel): + user_config: Annotated[ + LoopsUserConfig, Field(description="The updated Loops user config.") + ] + + class InstanceTypeWithPrice(BaseModel): instance_type: Annotated[ InstanceType, Field(description="Instance type properties.") @@ -441,6 +577,13 @@ class DeploymentArchivePayload(BaseModel): title="Labels", ), ] = None + is_development: Annotated[ + bool | None, + Field( + description="If true, push as a development deployment: the model's single mutable dev slot, created if absent and overwritten in place otherwise. The following fields must be left at their defaults: `environment_name`, `preserve_env_instance_type`, `deployment_name`.", + title="Is Development", + ), + ] = False class PrepareModelUploadRequest(BaseModel): @@ -478,13 +621,6 @@ class PrepareModelUploadRequest(BaseModel): title="Dry Run", ), ] = False - is_development: Annotated[ - bool | None, - Field( - description="If true, validate a development-deployment push. Only valid when `name` is set. The following `deployment` fields must be left at their defaults: `environment_name`, `preserve_env_instance_type`, `deployment_name`.", - title="Is Development", - ), - ] = False class AWSCredentials(BaseModel): @@ -573,6 +709,16 @@ class Models(BaseModel): models: Annotated[list[Model], Field(title="Models")] +class ModelsRequest(BaseModel): + name: Annotated[ + str | None, + Field( + description="When set, returns only models with this exact name, if any. On a team-scoped route this matches at most one model; on the org-wide route it may match models in multiple teams, since names are unique only within a team.", + title="Name", + ), + ] = None + + class LibraryListingSource(BaseModel): kind: Annotated[Literal["library_listing"], Field(title="Kind")] = "library_listing" lab_display_name: Annotated[ @@ -621,13 +767,6 @@ class ModelArchiveSource(BaseModel): title="Disable Archive Download", ), ] = False - is_development: Annotated[ - bool | None, - Field( - description="If true, push as a development deployment (the model's single mutable dev slot; overwrites any existing development deployment). The following `deployment` fields must be left at their defaults: `environment_name`, `preserve_env_instance_type`, `deployment_name`.", - title="Is Development", - ), - ] = False class CreateModelRequest(BaseModel): @@ -684,9 +823,9 @@ class AutoscalingSettings(BaseModel): ), ] = None max_scale_down_rate: Annotated[ - float | None, + int | None, Field( - description="Maximum rate at which replicas can scale down (e.g. 2.0 means at most halve replicas per window).", + description="Maximum percentage of replicas that can be removed per autoscaling window (1–50). E.g. 20 means at most 20% of replicas are removed per window.", title="Max Scale Down Rate", ), ] = None @@ -798,6 +937,16 @@ class Deployments(BaseModel): ] +class DeploymentsRequest(BaseModel): + name: Annotated[ + str | None, + Field( + description="When set, returns only the deployment with this exact name, if any.", + title="Name", + ), + ] = None + + class DeploymentArchiveSource(BaseModel): kind: Annotated[Literal["model_archive"], Field(title="Kind")] = "model_archive" deployment: Annotated[ @@ -835,14 +984,14 @@ class DeploymentTombstone(BaseModel): ] -class MaxScaleDownRate(RootModel[float]): +class MaxScaleDownRate(RootModel[int]): root: Annotated[ - float | None, + int | None, Field( - description="Maximum rate at which replicas can scale down (e.g. 2.0 means at most halve replicas per window).", - examples=[2.0], - gt=1.0, - le=2.0, + description="Maximum percentage of replicas that can be removed per autoscaling window (1–50). E.g. 20 means at most 20% of replicas are removed per window.", + examples=[20], + ge=1, + le=50, title="Max Scale Down Rate", ), ] = None @@ -907,8 +1056,8 @@ class UpdateAutoscalingSettings(BaseModel): max_scale_down_rate: Annotated[ MaxScaleDownRate | None, Field( - description="Maximum rate at which replicas can scale down (e.g. 2.0 means at most halve replicas per window).", - examples=[2.0], + description="Maximum percentage of replicas that can be removed per autoscaling window (1–50). E.g. 20 means at most 20% of replicas are removed per window.", + examples=[20], title="Max Scale Down Rate", ), ] = None @@ -1020,11 +1169,18 @@ class GetDeploymentConfigRequest(BaseModel): output_format: Annotated[ DeploymentConfigOutputFormat | None, Field( - description="'raw': verbatim config.yaml with comments — not available for deployments created before 2026-04-30. 'parsed': dict with server-side defaults applied — always available. 'both': both fields populated." + description="'raw': verbatim config.yaml with comments (not available for deployments created before 2026-04-30). 'parsed': dict with server-side defaults applied (always available). 'both': both fields populated." ), ] = DeploymentConfigOutputFormat.both +class LogLevel(Enum): + DEBUG = "DEBUG" + INFO = "INFO" + WARNING = "WARNING" + ERROR = "ERROR" + + class Log(BaseModel): timestamp: Annotated[ str, @@ -1049,6 +1205,12 @@ class Log(BaseModel): title="Request Id", ), ] = None + level: Annotated[ + LogLevel | None, + Field( + description="Severity of the log line, if one was detected. null when unknown." + ), + ] = None class GetLogsResponse(BaseModel): @@ -1064,7 +1226,7 @@ class SortOrder(Enum): class Limit(RootModel[int]): root: Annotated[ - int | None, + int, Field( description="Limit of logs to fetch in a single request", ge=1, @@ -1074,18 +1236,62 @@ class Limit(RootModel[int]): ] = 500 +class Replica(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="Only return logs emitted by this replica (5-char short ID).", + max_length=256, + title="Replica", + ), + ] = None + + +class RequestId(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="Only return logs tagged with this inference request ID.", + max_length=256, + title="Request Id", + ), + ] = None + + +class Component(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="Only return logs from this component.", + max_length=256, + title="Component", + ), + ] = None + + +class SearchPattern(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", + max_length=256, + title="Search Pattern", + ), + ] = None + + class GetDeploymentLogsRequest(BaseModel): start_epoch_millis: Annotated[ int | None, Field( - description="Epoch millis timestamp to start fetching logs", + description="Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", title="Start Epoch Millis", ), ] = None end_epoch_millis: Annotated[ int | None, Field( - description="Epoch millis timestamp to end fetching logs", + description="Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", title="End Epoch Millis", ), ] = None @@ -1100,78 +1306,458 @@ class GetDeploymentLogsRequest(BaseModel): title="Limit", ), ] - - -class TerminateReplicaResponse(BaseModel): - success: Annotated[ - bool | None, - Field( - description="Whether the replica was successfully terminated", - title="Success", - ), - ] = True - - -class SignSSHCertificateRequest(BaseModel): - public_key: Annotated[ - str, + min_level: Annotated[ + LogLevel | None, Field( - description="The user's SSH public key (e.g., 'ssh-ed25519 AAAA... user@host').", - title="Public Key", + description="Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." ), - ] - replica_id: Annotated[ - str | None, + ] = None + replica: Annotated[ + Replica | None, Field( - description="The replica to connect to. Required for training jobs (e.g. '0'). Optional for inference (server picks a running replica if omitted).", - title="Replica Id", + description="Only return logs emitted by this replica (5-char short ID).", + title="Replica", ), ] = None - - -class SignSSHCertificateResponse(BaseModel): - ssh_certificate: Annotated[ - str, + request_id: Annotated[ + RequestId | None, Field( - description="The signed SSH certificate in OpenSSH format.", - title="Ssh Certificate", + description="Only return logs tagged with this inference request ID.", + title="Request Id", ), - ] - jwt: Annotated[ - str, + ] = None + component: Annotated[ + Component | None, + Field(description="Only return logs from this component.", title="Component"), + ] = None + search_pattern: Annotated[ + SearchPattern | None, Field( - description="Signed JWT (ES256) for SSH proxy authorization.", title="Jwt" + description="RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", + title="Search Pattern", ), - ] - proxy_address: Annotated[ - str, + ] = None + includes: Annotated[ + list[str] | None, Field( - description="Address of the SSH proxy to connect to (host:port).", - title="Proxy Address", + description="Case-sensitive substrings that must all appear in the log message.", + max_length=8, + title="Includes", ), - ] - ssh_cert_expires_at: Annotated[ - AwareDatetime, + ] = None + excludes: Annotated[ + list[str] | None, Field( - description="When the certificate expires, in ISO 8601 format.", - title="Ssh Cert Expires At", + description="Case-sensitive substrings; lines containing any of these are dropped.", + max_length=8, + title="Excludes", ), - ] + ] = None -class InProgressPromotionStatus(Enum): - RELEASING = "RELEASING" - RAMPING_UP = "RAMPING_UP" - RAMPING_DOWN = "RAMPING_DOWN" - PAUSED = "PAUSED" - SUCCEEDED = "SUCCEEDED" - FAILED = "FAILED" - CANCELED = "CANCELED" +class DeploymentPatchAction(Enum): + ADD = "ADD" + UPDATE = "UPDATE" + REMOVE = "REMOVE" -class InProgressPromotion(BaseModel): - status: Annotated[ - InProgressPromotionStatus, Field(description="Status of the promotion") +class DeploymentPatchOpConfig(BaseModel): + type: Annotated[Literal["config"], Field(title="Type")] = "config" + config: Annotated[ + dict[str, Any], + Field(description="The full parsed config as a JSON object.", title="Config"), + ] + path: Annotated[ + str | None, + Field(description="Config file path within the source.", title="Path"), + ] = "config.yaml" + + +class DeploymentPatchOpEnvVar(BaseModel): + type: Annotated[Literal["environment_variable"], Field(title="Type")] = ( + "environment_variable" + ) + action: Annotated[ + DeploymentPatchAction, Field(description="How this op changes the variable.") + ] + name: Annotated[ + str, Field(description="The environment variable name.", title="Name") + ] + value: Annotated[ + str | None, + Field( + description="The environment variable value. Required for add and update.", + title="Value", + ), + ] = None + + +class DeploymentPatchOpExternalData(BaseModel): + type: Annotated[Literal["external_data"], Field(title="Type")] = "external_data" + action: Annotated[ + DeploymentPatchAction, + Field( + description="How this op changes the item. `UPDATE` is treated identically to `ADD`." + ), + ] + item: Annotated[ + dict[str, str], + Field(description="The single external data item descriptor.", title="Item"), + ] + + +class DeploymentPatchOpModelCode(BaseModel): + type: Annotated[Literal["model_code"], Field(title="Type")] = "model_code" + action: Annotated[ + DeploymentPatchAction, Field(description="How this op changes the file.") + ] + path: Annotated[ + str, + Field( + description="File path relative to the model code directory.", title="Path" + ), + ] + content: Annotated[ + str | None, + Field( + description="UTF-8 file content. Null for removals and binary files.", + title="Content", + ), + ] = None + content_bytes: Annotated[ + str | None, + Field( + description="Base64-encoded content for binary files.", + title="Content Bytes", + ), + ] = None + hot_reload: Annotated[ + bool | None, + Field( + description="Whether the running server can pick up this change without a restart.", + title="Hot Reload", + ), + ] = False + + +class DeploymentPatchOpPackage(BaseModel): + type: Annotated[Literal["package"], Field(title="Type")] = "package" + action: Annotated[ + DeploymentPatchAction, Field(description="How this op changes the file.") + ] + path: Annotated[ + str, + Field( + description="File path relative to the bundled packages directory.", + title="Path", + ), + ] + content: Annotated[ + str | None, + Field( + description="UTF-8 file content. Null for removals and binary files.", + title="Content", + ), + ] = None + content_bytes: Annotated[ + str | None, + Field( + description="Base64-encoded content for binary files.", + title="Content Bytes", + ), + ] = None + + +class DeploymentPatchOpPythonRequirement(BaseModel): + type: Annotated[Literal["python_requirement"], Field(title="Type")] = ( + "python_requirement" + ) + action: Annotated[ + DeploymentPatchAction, Field(description="How this op changes the requirement.") + ] + requirement: Annotated[ + str, + Field( + description="The requirement to apply. For removals this is the package name; otherwise the full requirements.txt-style line.", + title="Requirement", + ), + ] + + +class DeploymentPatchPoint(BaseModel): + content_hashes: Annotated[ + dict[str, str | None], + Field( + description="Map of every non-ignored source path, relative and forward-slash, to its content hash: files map to the hex blake3 digest of their bytes, directories map to null. This is the full signature of the source tree and what the content hash is derived from.", + title="Content Hashes", + ), + ] + config: Annotated[ + str, + Field( + description="The verbatim config.yaml text for this source state.", + title="Config", + ), + ] + requirements: Annotated[ + list[str] | None, + Field( + description="Requirements resolved from the config's requirements file, when it points at one. Empty when requirements are declared inline in the config.", + title="Requirements", + ), + ] = None + + +class PatchOps( + RootModel[ + DeploymentPatchOpModelCode + | DeploymentPatchOpPackage + | DeploymentPatchOpConfig + | DeploymentPatchOpPythonRequirement + | DeploymentPatchOpEnvVar + | DeploymentPatchOpExternalData + ] +): + root: Annotated[ + DeploymentPatchOpModelCode + | DeploymentPatchOpPackage + | DeploymentPatchOpConfig + | DeploymentPatchOpPythonRequirement + | DeploymentPatchOpEnvVar + | DeploymentPatchOpExternalData, + Field(discriminator="type"), + ] + + +class CreateDeploymentPatchRequest(BaseModel): + prev_patch_hash: Annotated[ + str, + Field( + description="Content hash of the patch point this patch is applied on - the link the staged patch must build on. A stale value (the base moved underneath the client) is rejected with a conflict.", + title="Prev Patch Hash", + ), + ] + next_patch_point: Annotated[ + DeploymentPatchPoint, + Field( + description="The source state after this patch. The server derives its content hash from `content_hashes`." + ), + ] + patch_ops: Annotated[ + list[PatchOps], + Field( + description="The ordered ops that make up this patch. At least one op is required; a patch that changes nothing is not a valid request. There is no op for a directory: a directory comes into existence when the first file under it is added, and is removed when its last file is removed, so directory creation and deletion happen implicitly through the file ops. Adding or removing an otherwise empty directory therefore produces no ops even though it changes the source hash; do not send a patch request for such a change.", + min_length=1, + title="Patch Ops", + ), + ] + + +class DeploymentPatchPointWithHash(BaseModel): + content_hashes: Annotated[ + dict[str, str | None], + Field( + description="Map of every non-ignored source path, relative and forward-slash, to its content hash: files map to the hex blake3 digest of their bytes, directories map to null. This is the full signature of the source tree and what the content hash is derived from.", + title="Content Hashes", + ), + ] + config: Annotated[ + str, + Field( + description="The verbatim config.yaml text for this source state.", + title="Config", + ), + ] + requirements: Annotated[ + list[str] | None, + Field( + description="Requirements resolved from the config's requirements file, when it points at one. Empty when requirements are declared inline in the config.", + title="Requirements", + ), + ] = None + hash: Annotated[ + str, + Field( + description="Content hash identifying this exact source state, and the link patches build on. It is derived deterministically from `content_hashes`, so a request need not send it - the server derives it. It is derived by sorting the `content_hashes` keys as paths, splitting each key on '/' into its path components and ordering the keys by comparing those component lists element by element, each component compared by Unicode code point (equivalently UTF-8 byte order). Treating '/' as a path separator this way, rather than as the ordinary character U+002F, means a key that is an ancestor path sorts before a sibling whose name extends the first differing component (so e.g. 'a/b' sorts before 'a.b'). A blake3 hasher is then built, and for each key in that order updated with the blake3 digest (32 raw bytes) of the key encoded as UTF-8, then, when the entry is a file (non-null value), with that file's digest as 32 raw bytes. The stream uses raw digest bytes, but the values in `content_hashes` are those digests hex-encoded (64 hex chars), so decode each value from hex first. Directory entries (null value) contribute only their key digest. The result is the hasher's own hex digest.", + title="Hash", + ), + ] + + +class CreateDeploymentPatchResponse(BaseModel): + patch_point: Annotated[ + DeploymentPatchPointWithHash, + Field( + description="The resulting patch point the staged patch produced; matches the pending point a subsequent state read returns." + ), + ] + + +class GetDeploymentPatchesStateResponse(BaseModel): + running_patch_point: Annotated[ + DeploymentPatchPointWithHash, + Field(description="The patch point the deployment is recorded as running."), + ] + pending_patch_point: Annotated[ + DeploymentPatchPointWithHash | None, + Field( + description="The latest staged-but-unsynced patch point, or null when the deployment is recorded as caught up." + ), + ] = None + + +class SyncDeploymentPatchesRequest(BaseModel): + pass + + +class SyncDeploymentPatchesResponse(BaseModel): + needs_full_deploy_reason: Annotated[ + str | None, + Field( + description="If set, the change cannot be patched and a full push is required; the value explains why. If null, the deployment is now in sync.", + title="Needs Full Deploy Reason", + ), + ] = None + + +class ModelMetricKind(Enum): + GAUGE = "GAUGE" + COUNTER = "COUNTER" + HISTOGRAM = "HISTOGRAM" + + +class ModelMetricMode(Enum): + CURRENT = "CURRENT" + SUMMARY = "SUMMARY" + SERIES = "SERIES" + + +class ModelMetricUnitHint(Enum): + PER_SECOND = "PER_SECOND" + SECONDS = "SECONDS" + BYTES = "BYTES" + MEBIBYTES = "MEBIBYTES" + COUNT = "COUNT" + RATIO = "RATIO" + + +class ModelMetricValueSet(BaseModel): + start_epoch_millis: Annotated[ + int, + Field( + description="Start of the step. The step spans until the next value set's start, or the window end for the last one; a summary has a single value set starting at the window start.", + title="Start Epoch Millis", + ), + ] + values: Annotated[ + list[list[float | None]], + Field( + description="Metric values aligned to the ``metric_descriptors`` index. Each entry is a list aligned to that descriptor's ``label_sets`` (a single-element list for a plain metric). A series with no data in this step is null.", + title="Values", + ), + ] + + +class GetDeploymentMetricsRequest(BaseModel): + mode: Annotated[ + ModelMetricMode | None, + Field( + description="'CURRENT': a single instantaneous snapshot at now; start/end must be omitted. 'SUMMARY': a single value set aggregating the whole window. 'SERIES': evenly-spaced value sets across the window, with the step derived from the window duration." + ), + ] = ModelMetricMode.CURRENT + start_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch millis timestamp to start fetching metrics. Defaults to one hour before the end.", + title="Start Epoch Millis", + ), + ] = None + end_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch millis timestamp to end fetching metrics. Defaults to the current time. The window between start and end must not exceed 7 days.", + title="End Epoch Millis", + ), + ] = None + metrics: Annotated[ + list[str] | None, + Field( + description="Names of the metrics to return; see https://docs.baseten.co/observability/export-metrics/supported-metrics for the available names. When omitted, a default set is returned: baseten_replicas_active, baseten_inference_requests_total, and baseten_end_to_end_response_time_seconds. Unknown names are rejected; valid names that do not apply are omitted from the response.", + title="Metrics", + ), + ] = None + + +class TerminateReplicaResponse(BaseModel): + success: Annotated[ + bool | None, + Field( + description="Whether the replica was successfully terminated", + title="Success", + ), + ] = True + + +class SignSSHCertificateRequest(BaseModel): + public_key: Annotated[ + str, + Field( + description="The user's SSH public key (e.g., 'ssh-ed25519 AAAA... user@host').", + title="Public Key", + ), + ] + replica_id: Annotated[ + str | None, + Field( + description="The replica to connect to. Required for training jobs (e.g. '0'). Optional for inference (server picks a running replica if omitted).", + title="Replica Id", + ), + ] = None + + +class SignSSHCertificateResponse(BaseModel): + ssh_certificate: Annotated[ + str, + Field( + description="The signed SSH certificate in OpenSSH format.", + title="Ssh Certificate", + ), + ] + jwt: Annotated[ + str, + Field( + description="Signed JWT (ES256) for SSH proxy authorization.", title="Jwt" + ), + ] + proxy_address: Annotated[ + str, + Field( + description="Address of the SSH proxy to connect to (host:port).", + title="Proxy Address", + ), + ] + ssh_cert_expires_at: Annotated[ + AwareDatetime, + Field( + description="When the certificate expires, in ISO 8601 format.", + title="Ssh Cert Expires At", + ), + ] + + +class InProgressPromotionStatus(Enum): + RELEASING = "RELEASING" + RAMPING_UP = "RAMPING_UP" + RAMPING_DOWN = "RAMPING_DOWN" + PAUSED = "PAUSED" + SUCCEEDED = "SUCCEEDED" + FAILED = "FAILED" + CANCELED = "CANCELED" + + +class InProgressPromotion(BaseModel): + status: Annotated[ + InProgressPromotionStatus, Field(description="Status of the promotion") ] percent_traffic_to_new_version: Annotated[ int, @@ -1204,40 +1790,145 @@ class UpdateRollingDeployConfig(BaseModel): rolling_deploy_strategy: Annotated[ RollingDeployStrategy | None, Field( - description="The rolling deploy strategy to use for promotions.", - examples=["REPLICA"], + description="The rolling deploy strategy to use for promotions.", + examples=["REPLICA"], + ), + ] = None + max_surge_percent: Annotated[ + int | None, + Field( + description="The maximum surge percentage for rolling deploys.", + examples=[25], + title="Max Surge Percent", + ), + ] = None + max_unavailable_percent: Annotated[ + int | None, + Field( + description="The maximum unavailable percentage for rolling deploys.", + examples=[10], + title="Max Unavailable Percent", + ), + ] = None + stabilization_time_seconds: Annotated[ + int | None, + Field( + description="The stabilization time in seconds for rolling deploys.", + examples=[300], + title="Stabilization Time Seconds", + ), + ] = None + replica_overhead_percent: Annotated[ + int | None, + Field( + description="The replica overhead percentage for rolling deploys.", + examples=[0], + title="Replica Overhead Percent", + ), + ] = None + + +class GetEnvironmentLogsRequest(BaseModel): + start_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + title="Start Epoch Millis", + ), + ] = None + end_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + title="End Epoch Millis", + ), + ] = None + direction: Annotated[SortOrder | None, Field(description="Sort order for logs")] = ( + None + ) + limit: Annotated[ + Limit | None, + Field( + default_factory=lambda: Limit(500), + description="Limit of logs to fetch in a single request", + title="Limit", + ), + ] + min_level: Annotated[ + LogLevel | None, + Field( + description="Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." + ), + ] = None + replica: Annotated[ + Replica | None, + Field( + description="Only return logs emitted by this replica (5-char short ID).", + title="Replica", + ), + ] = None + request_id: Annotated[ + RequestId | None, + Field( + description="Only return logs tagged with this inference request ID.", + title="Request Id", + ), + ] = None + component: Annotated[ + Component | None, + Field(description="Only return logs from this component.", title="Component"), + ] = None + search_pattern: Annotated[ + SearchPattern | None, + Field( + description="RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", + title="Search Pattern", + ), + ] = None + includes: Annotated[ + list[str] | None, + Field( + description="Case-sensitive substrings that must all appear in the log message.", + max_length=8, + title="Includes", ), ] = None - max_surge_percent: Annotated[ - int | None, + excludes: Annotated[ + list[str] | None, Field( - description="The maximum surge percentage for rolling deploys.", - examples=[10], - title="Max Surge Percent", + description="Case-sensitive substrings; lines containing any of these are dropped.", + max_length=8, + title="Excludes", ), - ] = 10 - max_unavailable_percent: Annotated[ + ] = None + + +class GetEnvironmentMetricsRequest(BaseModel): + mode: Annotated[ + ModelMetricMode | None, + Field( + description="'CURRENT': a single instantaneous snapshot at now; start/end must be omitted. 'SUMMARY': a single value set aggregating the whole window. 'SERIES': evenly-spaced value sets across the window, with the step derived from the window duration." + ), + ] = ModelMetricMode.CURRENT + start_epoch_millis: Annotated[ int | None, Field( - description="The maximum unavailable percentage for rolling deploys.", - examples=[10], - title="Max Unavailable Percent", + description="Epoch millis timestamp to start fetching metrics. Defaults to one hour before the end.", + title="Start Epoch Millis", ), ] = None - stabilization_time_seconds: Annotated[ + end_epoch_millis: Annotated[ int | None, Field( - description="The stabilization time in seconds for rolling deploys.", - examples=[300], - title="Stabilization Time Seconds", + description="Epoch millis timestamp to end fetching metrics. Defaults to the current time. The window between start and end must not exceed 7 days.", + title="End Epoch Millis", ), ] = None - replica_overhead_percent: Annotated[ - int | None, + metrics: Annotated[ + list[str] | None, Field( - description="The replica overhead percentage for rolling deploys.", - examples=[0], - title="Replica Overhead Percent", + description="Names of the metrics to return; see https://docs.baseten.co/observability/export-metrics/supported-metrics for the available names. When omitted, a default set is returned: baseten_replicas_active, baseten_inference_requests_total, and baseten_end_to_end_response_time_seconds. Unknown names are rejected; valid names that do not apply are omitted from the response.", + title="Metrics", ), ] = None @@ -1607,12 +2298,13 @@ class CreateJobWeightConfig(BaseModel): source: Annotated[ str, Field( - description="Weight source URI. Supported formats: hf://, s3://, gs://, r2://", + description="Weight source URI. Supported formats: hf://, s3://, gs://, r2://, cw://", examples=[ "hf://meta-llama/Llama-3-8B@main", "s3://my-bucket/models/llama", "gs://my-bucket/models/llama", "r2://account_id.bucket/models/llama", + "cw://my-bucket/models/llama", ], title="Source", ), @@ -1706,6 +2398,13 @@ class CreateTrainingJobCompute(BaseModel): examples=[{"accelerator": "H100", "count": 2}], ), ] = None + availability_model: Annotated[ + V1AvailabilityModel | None, + Field( + description="Capacity guarantee for the job. 'dedicated' (the default) runs on on-demand capacity that is not preempted. 'spot' runs on interruptible capacity that may be preempted; the user is responsible for checkpointing their own progress.", + examples=["spot"], + ), + ] = V1AvailabilityModel.dedicated class GcpOidcDockerAuth(BaseModel): @@ -1777,11 +2476,22 @@ class TrainingJobTombstone(BaseModel): ] +class UpdateTrainingJobRequest(BaseModel): + priority: Annotated[ + int, + Field( + description="New queue priority for a PENDING training job. Higher values are dequeued first. Only jobs in the PENDING state can have their priority changed.", + examples=[0, 10, 100], + title="Priority", + ), + ] + + class DownloadTrainingJobResponse(BaseModel): artifact_presigned_urls: Annotated[ list[str], Field( - description="Presigned URL's for the artifacts", + description="Presigned URLs for the job's uploaded artifacts.", title="Artifact Presigned Urls", ), ] @@ -1791,14 +2501,14 @@ class GetTrainingJobLogsRequest(BaseModel): start_epoch_millis: Annotated[ int | None, Field( - description="Epoch millis timestamp to start fetching logs", + description="Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", title="Start Epoch Millis", ), ] = None end_epoch_millis: Annotated[ int | None, Field( - description="Epoch millis timestamp to end fetching logs", + description="Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", title="End Epoch Millis", ), ] = None @@ -1813,6 +2523,12 @@ class GetTrainingJobLogsRequest(BaseModel): title="Limit", ), ] + min_level: Annotated[ + LogLevel | None, + Field( + description="Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." + ), + ] = None class TrainingJobMetric(BaseModel): @@ -1843,6 +2559,13 @@ class GetTrainingJobMetricsRequest(BaseModel): title="Start Epoch Millis", ), ] = None + step_seconds: Annotated[ + int | None, + Field( + description="Resolution of the returned series, in seconds. When omitted, a step is derived from the time range so large windows return fewer points.", + title="Step Seconds", + ), + ] = None class StopTrainingJobRequest(BaseModel): @@ -2159,269 +2882,25 @@ class SearchTrainingJobsRequest(BaseModel): description="Filter the training jobs by job ID.", examples=["p7qr9qv"], title="Job Id", - ), - ] = None - statuses: Annotated[ - list[str] | None, - Field( - description="Filter the training jobs by status.", - examples=[["TRAINING_JOB_RUNNING", "TRAINING_JOB_COMPLETED"]], - title="Statuses", - ), - ] = None - order_by: Annotated[ - list[OrderBy] | None, - Field( - default_factory=lambda: [ - OrderBy.model_validate(v) - for v in [{"field": "created_at", "order": "desc"}] - ], - description="Order the training jobs by a field. Currently supports created_at", - title="Order By", - ), - ] - - -class SearchTrainersRequest(BaseModel): - trainer_id: Annotated[ - str | None, - Field( - description="Filter by trainer ID.", - examples=["k4q95w5"], - title="Trainer Id", - ), - ] = None - - -class SearchedTrainer(BaseModel): - trainer_id: Annotated[str, Field(description="The trainer ID.", title="Trainer Id")] - session_id: Annotated[ - str, - Field( - description="The session ID this trainer belongs to.", title="Session Id" - ), - ] - base_model: Annotated[ - str, - Field( - description="The HuggingFace base model the trainer is fine-tuning.", - title="Base Model", - ), - ] - - -class SearchTrainersResponse(BaseModel): - trainers: Annotated[ - list[SearchedTrainer], Field(description="List of trainers.", title="Trainers") - ] - - -class CheckpointSearchRequest(BaseModel): - checkpoint_path: Annotated[ - str, - Field( - description="bt:// URI of a trainer checkpoint. Form: bt://loops:/(weights|sampler_weights)/.", - examples=["bt://loops:k4q95w5/sampler_weights/step-100"], - title="Checkpoint Path", - ), - ] - - -class TrainerServerCheckpoint(BaseModel): - checkpoint_id: Annotated[ - str, Field(description="The ID of the checkpoint.", title="Checkpoint Id") - ] - created_at: Annotated[ - AwareDatetime, - Field( - description="The timestamp of the checkpoint in ISO 8601 format.", - title="Created At", - ), - ] - checkpoint_type: Annotated[ - str, Field(description="The type of checkpoint.", title="Checkpoint Type") - ] - base_model: Annotated[ - str | None, - Field(description="The base model of the checkpoint.", title="Base Model"), - ] - lora_adapter_config: Annotated[ - dict[str, Any] | None, - Field( - description="The adapter config of the checkpoint.", - title="Lora Adapter Config", - ), - ] - size_bytes: Annotated[ - int, - Field(description="The size of the checkpoint in bytes.", title="Size Bytes"), - ] - sync_status: Annotated[ - str | None, - Field( - description="Sync state of the checkpoint: SYNCING or COMPLETE.", - title="Sync Status", - ), - ] = None - id: Annotated[ - str, Field(description="The TrainerServerCheckpoint database ID.", title="Id") - ] - trainer_id: Annotated[ - str, Field(description="The ID of the trainer.", title="Trainer Id") - ] - target: Annotated[ - TrainerCheckpointTarget, - Field( - description="Whether this checkpoint is loadable by the sampler ('sampler') or by the trainer ('trainer')." - ), - ] - - -class CheckpointSearchResponse(BaseModel): - checkpoint: Annotated[ - TrainerServerCheckpoint, - Field(description="The checkpoint metadata (id, target, type, sizes, etc.)."), - ] - - -class CreateTrainerSessionRequest(BaseModel): - training_project_id: Annotated[ - str | None, - Field( - description="ID of the training project to associate with. If omitted, a default project is created for the org.", - title="Training Project Id", - ), - ] = None - - -class TrainerSession(BaseModel): - id: Annotated[str, Field(title="Id")] - - -class CreateTrainerSessionResponse(BaseModel): - session: TrainerSession - - -class CreateTrainerServerRequest(BaseModel): - model: Annotated[ - str, Field(description="Base model ID (e.g. 'Qwen/Qwen3-8B').", title="Model") - ] - max_seq_len: Annotated[ - int | None, - Field( - description="Maximum sequence length for training. Defaults to the maximum supported by the model configuration.", - title="Max Seq Len", - ), - ] = None - lora_rank: Annotated[ - int | None, Field(description="LoRA rank.", title="Lora Rank") - ] = 64 - seed: Annotated[ - int | None, Field(description="Random seed for reproducibility.", title="Seed") - ] = None - scale_down_delay_seconds: Annotated[ - int | None, - Field( - description="Seconds of inactivity before the trainer scales to zero. Must be positive. Defaults to 3600 (1 hour).", - gt=0, - title="Scale Down Delay Seconds", - ), - ] = 3600 - checkpoint_path: Annotated[ - str | None, - Field( - description="Optional bt:// URI of an existing trainer-target checkpoint to resume training from. Form: bt://loops:/weights/.", - examples=["bt://loops:k4q95w5/weights/step-100"], - title="Checkpoint Path", - ), - ] = None - - -class SamplingServer(BaseModel): - id: Annotated[str, Field(title="Id")] - base_url: Annotated[str, Field(title="Base Url")] - model_id: Annotated[ - str, - Field(description="Hashid of the underlying Baseten model.", title="Model Id"), - ] - deployment_id: Annotated[ - str, - Field( - description="Hashid of the specific model deployment (version).", - title="Deployment Id", - ), - ] - - -class TrainerServer(BaseModel): - id: Annotated[str, Field(title="Id")] - base_url: Annotated[str, Field(title="Base Url")] - sampling_server: SamplingServer - - -class CreateTrainerServerResponse(BaseModel): - trainer_server: TrainerServer - - -class CreateSamplingServerRequest(BaseModel): - model: Annotated[ - str, - Field( - description="Model to use for standalone samplers (eg, for baselines).", - title="Model", - ), - ] - max_seq_length: Annotated[ - int | None, - Field( - description="Maximum prompt length (in tokens) the sampler must handle. Set this to the longest prompt you plan to send. Omit to use the default for the base model.", - title="Max Seq Length", - ), - ] = None - checkpoint_path: Annotated[ - str | None, - Field( - description="Optional bt:// URI of an existing sampler-target checkpoint to load weights from on startup. Form: bt://loops:/sampler_weights/.", - examples=["bt://loops:k4q95w5/sampler_weights/step-100"], - title="Checkpoint Path", - ), - ] = None - - -class CreateSamplingServerResponse(BaseModel): - sampling_server: SamplingServer - - -class GetTrainerServerCheckpointsResponse(BaseModel): - trainer_id: Annotated[ - str, Field(description="The ID of the trainer.", title="Trainer Id") - ] - checkpoints: Annotated[ - list[TrainerServerCheckpoint], - Field(description="The checkpoints for the trainer.", title="Checkpoints"), - ] - - -class GetTrainerServerCheckpointFilesResponse(BaseModel): - presigned_urls: Annotated[ - list[CheckpointFile], - Field( - description="List of presigned URLs for checkpoint files.", - title="Presigned Urls", - ), - ] - next_page_token: Annotated[ - int | None, + ), + ] = None + statuses: Annotated[ + list[str] | None, Field( - description="Token to use for fetching the next page of results. None when there are no more results.", - title="Next Page Token", + description="Filter the training jobs by status.", + examples=[["TRAINING_JOB_RUNNING", "TRAINING_JOB_COMPLETED"]], + title="Statuses", ), ] = None - total_count: Annotated[ - int, + order_by: Annotated[ + list[OrderBy] | None, Field( - description="Total number of checkpoint files available.", - title="Total Count", + default_factory=lambda: [ + OrderBy.model_validate(v) + for v in [{"field": "created_at", "order": "desc"}] + ], + description="Order the training jobs by a field. Currently supports created_at", + title="Order By", ), ] @@ -2449,16 +2928,6 @@ class GetLoopsCapabilitiesResponse(BaseModel): ] -class CreateLoopsSessionRequest(BaseModel): - training_project_id: Annotated[ - str | None, - Field( - description="ID of the training project to associate with. If omitted, a default project is created for the org.", - title="Training Project Id", - ), - ] = None - - class LoopsSession(BaseModel): id: Annotated[str, Field(title="Id")] @@ -2525,6 +2994,18 @@ class ListLoopsRunsQueryParams(BaseModel): ] = None +class Name1(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="Optional display name for the run. Defaults to the base model name when omitted.", + max_length=255, + min_length=1, + title="Name", + ), + ] = None + + class CreateLoopsRunRequest(BaseModel): session_id: Annotated[ str, @@ -2537,6 +3018,13 @@ class CreateLoopsRunRequest(BaseModel): str, Field(description="Base model ID (e.g. 'Qwen/Qwen3-8B').", title="Base Model"), ] + name: Annotated[ + Name1 | None, + Field( + description="Optional display name for the run. Defaults to the base model name when omitted.", + title="Name", + ), + ] = None max_seq_len: Annotated[ int | None, Field( @@ -2553,11 +3041,20 @@ class CreateLoopsRunRequest(BaseModel): scale_down_delay_seconds: Annotated[ int | None, Field( - description="Seconds of inactivity before the run scales to zero. Must be positive. Defaults to 3600 (1 hour).", + description="Seconds of inactivity before the run scales to zero. Must be between 1 and 3600 (1 hour). Defaults to 3600.", gt=0, + le=3600, title="Scale Down Delay Seconds", ), ] = 3600 + replicas: Annotated[ + int | None, + Field( + description="Number of data-parallel trainer replicas. Each replica is one full copy of the model's preset node group, so the trainer deployment runs (preset node_count * replicas) nodes (e.g. replicas=4 on a 4-node preset → 16 nodes, 4 DP workers). Must be a positive integer. Defaults to 1.", + ge=1, + title="Replicas", + ), + ] = 1 path: Annotated[ str | None, Field( @@ -2569,7 +3066,7 @@ class CreateLoopsRunRequest(BaseModel): reuse_from_session_id: Annotated[ str | None, Field( - description="Optional Loops session ID whose trainer deployment should be reused for this run, sharing the infrastructure across sessions instead of provisioning fresh. The named session must belong to the same team. Reuse is best-effort: if the prior deployment is stopped, failed, or its sampler is unhealthy, a new deployment is provisioned instead.", + description="Optional Loops session ID whose trainer deployment should be reused for this run, sharing the infrastructure across sessions instead of provisioning fresh. The named session must belong to the same team. Reuse is best-effort: if the prior deployment is stopped, failed, its sampler is unhealthy, or this run requests replicas != 1, a new deployment is provisioned instead.", title="Reuse From Session Id", ), ] = None @@ -2759,6 +3256,13 @@ class LoopsDeploymentStatus(BaseModel): class LoopsDeployment(BaseModel): id: Annotated[str, Field(description="The Loops deployment ID.", title="Id")] + active_run_id: Annotated[ + str | None, + Field( + description="The ID of the run currently active on this deployment, if any. Null when the deployment's runs have been marked inactive (e.g. scale-to-zero) without a successor.", + title="Active Run Id", + ), + ] = None base_model: Annotated[ str, Field( @@ -2770,9 +3274,10 @@ class LoopsDeployment(BaseModel): status: Annotated[ LoopsDeploymentStatus, Field(description="Latest deployment status.") ] + user: Annotated[User, Field(description="The user who owns the Loops deployment.")] sampler: Annotated[ - LoopsSampler, Field(description="The sampler bound to this deployment.") - ] + LoopsSampler | None, Field(description="The sampler bound to this deployment.") + ] = None class ListLoopsDeploymentsResponse(BaseModel): @@ -2815,6 +3320,20 @@ class GetLoopsDeploymentMetricsRequest(BaseModel): title="Start Epoch Millis", ), ] = None + step_seconds: Annotated[ + int | None, + Field( + description="Resolution of the returned series, in seconds. When omitted, a step is derived from the time range so large windows return fewer points.", + title="Step Seconds", + ), + ] = None + time_divisor_seconds: Annotated[ + int | None, + Field( + description="Unit of time for request-volume metrics, in seconds (e.g. 60 for requests/minute). Defaults to per-second.", + title="Time Divisor Seconds", + ), + ] = None class InferenceVolumeByStatusDatapoint(BaseModel): @@ -2827,99 +3346,370 @@ class InferenceVolumeByStatusDatapoint(BaseModel): status_4xx: Annotated[ float, Field(description="4xx requests per second.", title="Status 4Xx") ] - status_5xx: Annotated[ - float, Field(description="5xx requests per second.", title="Status 5Xx") + status_5xx: Annotated[ + float, Field(description="5xx requests per second.", title="Status 5Xx") + ] + + +class ResponseTimeDatapoint(BaseModel): + timestamp: Annotated[ + AwareDatetime, Field(description="ISO 8601 timestamp.", title="Timestamp") + ] + p50: Annotated[ + float | None, + Field( + description="50th percentile request latency (milliseconds).", title="P50" + ), + ] = None + p95: Annotated[ + float | None, + Field( + description="95th percentile request latency (milliseconds).", title="P95" + ), + ] = None + p99: Annotated[ + float | None, + Field( + description="99th percentile request latency (milliseconds).", title="P99" + ), + ] = None + + +class GetLoopsDeploymentLogsRequest(BaseModel): + start_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + title="Start Epoch Millis", + ), + ] = None + end_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + title="End Epoch Millis", + ), + ] = None + direction: Annotated[SortOrder | None, Field(description="Sort order for logs")] = ( + None + ) + limit: Annotated[ + Limit | None, + Field( + default_factory=lambda: Limit(500), + description="Limit of logs to fetch in a single request", + title="Limit", + ), + ] + min_level: Annotated[ + LogLevel | None, + Field( + description="Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." + ), + ] = None + + +class TeamTrainingGpuCapacityItem(BaseModel): + team_id: Annotated[str, Field(description="Team identifier", title="Team Id")] + team_name: Annotated[str, Field(description="Team name", title="Team Name")] + gpu_type: Annotated[ + str, + Field( + description="GPU type identifier (e.g. H100, A100-40GB)", title="Gpu Type" + ), + ] + baseline: Annotated[ + int, + Field( + description="Baseline GPU allocation for the team. 0 if not configured.", + title="Baseline", + ), + ] + limit: Annotated[ + int, + Field( + description="Maximum concurrent GPUs of this type for this team", + title="Limit", + ), + ] + usage_count: Annotated[ + int, + Field( + description="GPUs currently in use by the team's active training jobs", + title="Usage Count", + ), + ] + + +class TrainingGpuCapacityItem(BaseModel): + gpu_type: Annotated[ + str, + Field( + description="GPU type identifier (e.g. H100, A100-40GB)", title="Gpu Type" + ), + ] + baseline: Annotated[ + int, + Field( + description="Baseline GPU allocation; jobs below this threshold are expected to run immediately. 0 if not configured.", + title="Baseline", + ), + ] + limit: Annotated[ + int, + Field( + description="Maximum concurrent GPUs of this type for this org", + title="Limit", + ), + ] + usage_count: Annotated[ + int, + Field( + description="GPUs currently in use by active training jobs", + title="Usage Count", + ), + ] + + +class GetTrainingGpuCapacityResponse(BaseModel): + gpu_capacities: Annotated[ + list[TrainingGpuCapacityItem], + Field( + description="Org-level GPU capacity limits and current usage per GPU type", + title="Gpu Capacities", + ), + ] + team_gpu_capacities: Annotated[ + list[TeamTrainingGpuCapacityItem] | None, + Field( + description="Per-team GPU capacity limits and current usage per GPU type", + title="Team Gpu Capacities", + ), + ] = None + + +class PatchTeamTrainingGpuCapacityRequest(BaseModel): + team_id: Annotated[str, Field(description="Team identifier", title="Team Id")] + gpu_type: Annotated[ + str, + Field( + description="GPU type identifier (e.g. H100, A100-40GB)", title="Gpu Type" + ), + ] + max_gpus: Annotated[ + int, + Field( + description="Max concurrent GPUs of this type the team may use", + examples=[8, 16, 32], + title="Max Gpus", + ), + ] + + +class PatchTeamTrainingGpuCapacityResponse(BaseModel): + team_gpu_capacity: Annotated[ + TeamTrainingGpuCapacityItem, + Field(description="The updated per-team GPU capacity limit"), + ] + + +class ActiveJobAtSubmit(BaseModel): + training_job_id: Annotated[ + str, + Field(description="Hashid of the other training job", title="Training Job Id"), + ] + training_job_name: Annotated[ + str | None, Field(description="Other job's name", title="Training Job Name") + ] = None + instance_type_name: Annotated[ + str, + Field(description="Instance type of the other job", title="Instance Type Name"), + ] + total_gpus: Annotated[ + int, Field(description="gpu_count * effective_node_count", title="Total Gpus") + ] + workload_plane_name: Annotated[ + str, + Field( + description="Workload plane the other job was on", + title="Workload Plane Name", + ), + ] + status_at_submit: Annotated[ + str, + Field( + description="Other job's status as of submitted_at (one of ACTIVE_STATES)", + title="Status At Submit", + ), + ] + status_set_at: Annotated[ + AwareDatetime, + Field(description="When that status was set", title="Status Set At"), + ] + + +class CapacityAtSubmit(BaseModel): + gpu_type: Annotated[ + str, + Field( + description="GPU type identifier (e.g. H100, A100-40GB)", title="Gpu Type" + ), + ] + max_gpus: Annotated[ + int, + Field(description="Current max concurrent GPUs of this type", title="Max Gpus"), + ] + min_gpus: Annotated[ + int | None, + Field( + description="Current baseline GPU allocation, if configured", + title="Min Gpus", + ), + ] = None + last_modified: Annotated[ + AwareDatetime, + Field( + description="When the capacity row was last modified", title="Last Modified" + ), + ] + + +class PendingJobAheadAtSubmit(BaseModel): + training_job_id: Annotated[ + str, + Field(description="Hashid of the other training job", title="Training Job Id"), + ] + training_job_name: Annotated[ + str | None, Field(description="Other job's name", title="Training Job Name") + ] = None + instance_type_name: Annotated[ + str, + Field(description="Instance type of the other job", title="Instance Type Name"), + ] + requested_gpus: Annotated[ + int, + Field(description="gpu_count * effective_node_count", title="Requested Gpus"), + ] + priority: Annotated[ + int, + Field(description="Effective priority (NULL coalesced to 0)", title="Priority"), + ] + submitted_at: Annotated[ + AwareDatetime, + Field(description="The other job's submission time", title="Submitted At"), ] -class ResponseTimeDatapoint(BaseModel): - timestamp: Annotated[ - AwareDatetime, Field(description="ISO 8601 timestamp.", title="Timestamp") - ] - p50: Annotated[ - float | None, +class QueueEvent(BaseModel): + training_job_id: Annotated[ + str, Field( - description="50th percentile request latency (milliseconds).", title="P50" + description="Hashid of the training job this event is for", + title="Training Job Id", ), + ] + training_job_name: Annotated[ + str | None, Field(description="Job name", title="Training Job Name") ] = None - p95: Annotated[ - float | None, + status: Annotated[ + str, Field(description="TrainingJobStatus.Name value", title="Status") + ] + created: Annotated[ + AwareDatetime, + Field(description="When the status row was inserted", title="Created"), + ] + event_message: Annotated[ + str | None, Field( - description="95th percentile request latency (milliseconds).", title="P95" + description="Human-readable event message from the status metadata", + title="Event Message", ), ] = None - p99: Annotated[ - float | None, + exit_code: Annotated[ + int | None, Field( - description="99th percentile request latency (milliseconds).", title="P99" + description="Exit code from the status metadata, if any", title="Exit Code" ), ] = None -class GetLoopsDeploymentLogsRequest(BaseModel): - start_epoch_millis: Annotated[ - int | None, +class GetTrainingJobQueueContextResponse(BaseModel): + target_job_id: Annotated[ + str, + Field(description="Hashid of the target training job", title="Target Job Id"), + ] + target_job_name: Annotated[ + str | None, Field(description="Target job's name", title="Target Job Name") + ] = None + gpu_type: Annotated[ + str, Field(description="GPU type the target requested", title="Gpu Type") + ] + requested_gpus: Annotated[ + int, Field( - description="Epoch millis timestamp to start fetching logs", - title="Start Epoch Millis", + description="GPUs the target requested (gpu_count * effective_node_count)", + title="Requested Gpus", + ), + ] + submitted_at: Annotated[ + AwareDatetime, + Field( + description="When the job row was inserted (= API POST time)", + title="Submitted At", + ), + ] + released_at: Annotated[ + AwareDatetime | None, + Field( + description="When the job's TRAINING_JOB_CREATED status was set, i.e. the moment it was released from PENDING. None if still PENDING.", + title="Released At", ), ] = None - end_epoch_millis: Annotated[ + pending_seconds: Annotated[ int | None, Field( - description="Epoch millis timestamp to end fetching logs", - title="End Epoch Millis", + description="released_at - submitted_at in seconds. None if still PENDING.", + title="Pending Seconds", ), ] = None - direction: Annotated[SortOrder | None, Field(description="Sort order for logs")] = ( - None - ) - limit: Annotated[ - Limit | None, + org_capacity: Annotated[ + CapacityAtSubmit | None, Field( - default_factory=lambda: Limit(500), - description="Limit of logs to fetch in a single request", - title="Limit", + description="Org-level cap for (org, gpu_type). None if no cap is configured." ), - ] - - -class TrainingGpuCapacityItem(BaseModel): - gpu_type: Annotated[ - str, + ] = None + team_capacity: Annotated[ + CapacityAtSubmit | None, Field( - description="GPU type identifier (e.g. H100, A100-40GB)", title="Gpu Type" + description="Team-level cap for (team, gpu_type). None if no team cap is configured." ), - ] - baseline: Annotated[ - int, + ] = None + active_at_submit: Annotated[ + list[ActiveJobAtSubmit], Field( - description="Baseline GPU allocation; jobs below this threshold are expected to run immediately. 0 if not configured.", - title="Baseline", + description="Jobs in the same (org, gpu_type) pool that were holding capacity at submitted_at", + title="Active At Submit", ), ] - limit: Annotated[ - int, + pending_ahead_at_submit: Annotated[ + list[PendingJobAheadAtSubmit], Field( - description="Maximum concurrent GPUs of this type for this org", - title="Limit", + description="PENDING jobs in the same (org, gpu_type) pool that were ahead of the target in dequeue FIFO order at submitted_at (priority DESC then created ASC). These also block the target's release.", + title="Pending Ahead At Submit", ), ] - usage_count: Annotated[ - int, + events: Annotated[ + list[QueueEvent], Field( - description="GPUs currently in use by active training jobs", - title="Usage Count", + description="Every status event in [submitted_at, events_window_end] for the target job, every job in active_at_submit, and every job in pending_ahead_at_submit, oldest first.", + title="Events", ), ] - - -class GetTrainingGpuCapacityResponse(BaseModel): - gpu_capacities: Annotated[ - list[TrainingGpuCapacityItem], + events_window_end: Annotated[ + AwareDatetime, Field( - description="GPU capacity limits and current usage per GPU type", - title="Gpu Capacities", + description="released_at if set, else 'now' (events ongoing)", + title="Events Window End", ), ] @@ -2971,54 +3761,18 @@ class APIKey(BaseModel): api_key: Annotated[str, Field(description="The API key string", title="Api Key")] -class APIKeyInfo(BaseModel): - prefix: Annotated[ - str, Field(description="The prefix of the API key", title="Prefix") - ] - name: Annotated[ - str | None, - Field( - description="Optional name for the API key", - examples=["my-api-key"], - title="Name", - ), - ] = None - type: Annotated[ - APIKeyCategory, - Field( - description="Type of the API key.", - examples=[ - "PERSONAL", - "WORKSPACE_EXPORT_METRICS", - "WORKSPACE_INVOKE", - "WORKSPACE_MANAGE_ALL", - ], - ), +class APIKeyOwner(BaseModel): + user_id: Annotated[ + str, Field(description="Unique identifier for the user", title="User Id") ] - model_ids: Annotated[ - list[str] | None, - Field( - description="List of model IDs to scope the API key to, only present if type is 'WORKSPACE_EXPORT_METRICS' or 'WORKSPACE_INVOKE'", - examples=[["aaaaaaaa"]], - title="Model Ids", - ), + email: Annotated[ + str | None, Field(description="Email address of the user", title="Email") ] = None - team_name: Annotated[ - str | None, - Field( - description="The name of the team associated with the API key", - title="Team Name", - ), + name: Annotated[ + str | None, Field(description="Display name of the user", title="Name") ] = None -class APIKeys(BaseModel): - keys: Annotated[ - list[APIKeyInfo], - Field(description="A list of API key information", title="Keys"), - ] - - class APIKeyTombstone(BaseModel): prefix: Annotated[ str, Field(description="Unique prefix of the API key", title="Prefix") @@ -3048,6 +3802,109 @@ class CreateModelWeightSnapshotRequest(BaseModel): ] +class LimitType(Enum): + REQUEST = "REQUEST" + TOKEN = "TOKEN" + + +class ModelAPIOrgDetails(BaseModel): + added_at: Annotated[ + AwareDatetime, + Field( + description="When the workspace first added this Model API.", + title="Added At", + ), + ] + last_used_at: Annotated[ + AwareDatetime | None, + Field( + description="When the workspace last invoked this Model API. Null if the workspace has never invoked it.", + title="Last Used At", + ), + ] = None + + +class CostPerMillionInputTokens(RootModel[str]): + model_config = ConfigDict( + regex_engine="python-re", + ) + root: Annotated[ + str, + Field( + description="Cost per million input tokens, in dollars.", + examples=["0.13"], + pattern="^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + title="Cost Per Million Input Tokens", + ), + ] + + +class CostPerMillionOutputTokens(RootModel[str]): + model_config = ConfigDict( + regex_engine="python-re", + ) + root: Annotated[ + str, + Field( + description="Cost per million output tokens, in dollars.", + examples=["0.50"], + pattern="^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + title="Cost Per Million Output Tokens", + ), + ] + + +class RateLimitUnit(Enum): + SECOND = "SECOND" + MINUTE = "MINUTE" + + +class RateLimit(BaseModel): + type: Annotated[ + LimitType, + Field(description="The type of the rate limit", examples=["TOKEN", "REQUEST"]), + ] + unit: Annotated[ + RateLimitUnit, + Field(description="The unit of the rate limit", examples=["SECOND", "MINUTE"]), + ] + threshold: Annotated[ + int, + Field( + description="The threshold for the rate limit", + examples=[1000, 50000], + ge=0, + title="Threshold", + ), + ] + + +class ModelAPIsRequest(BaseModel): + cursor: Annotated[ + str | None, + Field( + description="Opaque cursor returned by a previous page. Omit to fetch the first page.", + title="Cursor", + ), + ] = None + limit: Annotated[ + int | None, + Field( + description="Maximum number of items to return.", + ge=1, + le=1000, + title="Limit", + ), + ] = 100 + added_only: Annotated[ + bool | None, + Field( + description="When true, restrict the result to Model APIs the workspace has added. Defaults to the full visible catalog.", + title="Added Only", + ), + ] = False + + class CreateLLMModelRequest(BaseModel): resources: Annotated[ dict[str, Any], @@ -3055,8 +3912,8 @@ class CreateLLMModelRequest(BaseModel): ] llm_version: Annotated[ str | None, - Field(description="Version of the helm chart to use", title="Llm Version"), - ] = "1.0" + Field(description="Version of the helm chart to use.", title="Llm Version"), + ] = None llm_config: Annotated[ dict[str, Any] | None, Field( @@ -3156,8 +4013,8 @@ class CreateLLMModelVersionRequest(BaseModel): ] llm_version: Annotated[ str | None, - Field(description="Version of the helm chart to use", title="Llm Version"), - ] = "1.0" + Field(description="Version of the helm chart to use.", title="Llm Version"), + ] = None llm_config: Annotated[ dict[str, Any] | None, Field( @@ -3247,6 +4104,13 @@ class LibraryListing(BaseModel): description="Whether the listing is publicly accessible", title="Is Public" ), ] + closed_source: Annotated[ + bool, + Field( + description="Whether the listing is closed source (deployers cannot view or download the Truss, and forks copy mirrored weights instead of re-mirroring from upstream)", + title="Closed Source", + ), + ] created_at: Annotated[ AwareDatetime, Field( @@ -3282,6 +4146,13 @@ class CreateLibraryListingRequest(BaseModel): description="Whether the listing is publicly accessible", title="Is Public" ), ] = False + closed_source: Annotated[ + bool | None, + Field( + description="Whether the listing is closed source (deployers cannot view or download the Truss, and forks copy mirrored weights instead of re-mirroring from upstream)", + title="Closed Source", + ), + ] = False class LibraryListingTombstone(BaseModel): @@ -3379,6 +4250,13 @@ class CreateLibraryListingVersionRequest(BaseModel): title="Allow Truss Download", ), ] = False + closed_source: Annotated[ + bool | None, + Field( + description="Whether the listing is closed source (deployers cannot view or download the Truss, and forks copy mirrored weights instead of re-mirroring from upstream). Only used when creating a new listing.", + title="Closed Source", + ), + ] = False version_tag: Annotated[ str, Field(description="Human-readable tag for this version", title="Version Tag"), @@ -3413,35 +4291,63 @@ class UpdateLibraryListingVersionRequest(BaseModel): description="Whether users deploying this model can download the Truss", title="Allow Truss Download", ), - ] = None + ] = None + + +class ChainMetadata(BaseModel): + chain_id: Annotated[ + str, Field(description="Unique identifier of the chain", title="Chain Id") + ] + chain_name: Annotated[ + str | None, Field(description="Name of the chain", title="Chain Name") + ] = None + chain_deployment_id: Annotated[ + str, + Field( + description="Unique identifier of the chain deployment", + title="Chain Deployment Id", + ), + ] + + +class Subtotal(RootModel[str]): + model_config = ConfigDict( + regex_engine="python-re", + ) + root: Annotated[ + str, + Field( + description="Subtotal cost incurred on this date in dollars", + pattern="^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + title="Subtotal", + ), + ] -class ChainMetadata(BaseModel): - chain_id: Annotated[ - str, Field(description="Unique identifier of the chain", title="Chain Id") - ] - chain_name: Annotated[ - str | None, Field(description="Name of the chain", title="Chain Name") - ] = None - chain_deployment_id: Annotated[ +class ComputeCost(RootModel[str]): + model_config = ConfigDict( + regex_engine="python-re", + ) + root: Annotated[ str, Field( - description="Unique identifier of the chain deployment", - title="Chain Deployment Id", + description="Compute cost incurred on this date in dollars", + pattern="^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + title="Compute Cost", ), ] -class Subtotal(RootModel[str]): +class SurchargeCost(RootModel[str]): model_config = ConfigDict( regex_engine="python-re", ) root: Annotated[ str, Field( - description="Subtotal cost incurred on this date in dollars", + description="Model distribution surcharge incurred on this date in dollars", pattern="^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - title="Subtotal", + title="Surcharge Cost", ), ] @@ -3455,6 +4361,20 @@ class DailyDedicatedUsage(BaseModel): title="Subtotal", ), ] + compute_cost: Annotated[ + float | ComputeCost, + Field( + description="Compute cost incurred on this date in dollars", + title="Compute Cost", + ), + ] + surcharge_cost: Annotated[ + float | SurchargeCost, + Field( + description="Model distribution surcharge incurred on this date in dollars", + title="Surcharge Cost", + ), + ] minutes: Annotated[ int, Field(description="Minutes used on this date", title="Minutes") ] @@ -3523,6 +4443,34 @@ class Subtotal3(RootModel[str]): ] +class ComputeCost1(RootModel[str]): + model_config = ConfigDict( + regex_engine="python-re", + ) + root: Annotated[ + str, + Field( + description="Compute cost in dollars for this billable resource", + pattern="^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + title="Compute Cost", + ), + ] + + +class SurchargeCost1(RootModel[str]): + model_config = ConfigDict( + regex_engine="python-re", + ) + root: Annotated[ + str, + Field( + description="Model distribution surcharge in dollars for this billable resource", + pattern="^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + title="Surcharge Cost", + ), + ] + + class Subtotal4(RootModel[str]): model_config = ConfigDict( regex_engine="python-re", @@ -3706,71 +4654,282 @@ class UserInfo(BaseModel): ] = None -class Name1(RootModel[str]): - root: Annotated[ +class UsersResponse(BaseModel): + items: Annotated[ + list[UserInfo], Field(description="Items in this page.", title="Items") + ] + pagination: Annotated[ + PaginationResponse, Field(description="Pagination metadata for the page.") + ] + + +class UsersRequest(BaseModel): + cursor: Annotated[ str | None, Field( - description="Optional display name for the group.", - examples=["Acme prod"], - max_length=255, - title="Name", + description="Opaque cursor returned by a previous page. Omit to fetch the first page.", + title="Cursor", + ), + ] = None + limit: Annotated[ + int | None, + Field( + description="Maximum number of items to return.", + ge=1, + le=1000, + title="Limit", + ), + ] = 100 + email: Annotated[ + str | None, + Field( + description="When set, returns only users with this exact email, if any.", + title="Email", ), ] = None -class GroupMetadata(BaseModel): - name: Annotated[ - Name1 | None, +class EndpointTarget(BaseModel): + provider: Annotated[GatewayProvider, Field(description="Upstream provider.")] + secret_id: Annotated[ + str | None, Field(description="Referenced secret, if any.", title="Secret Id") + ] = None + target_model: Annotated[ + str | None, + Field(description="Upstream model name, if any.", title="Target Model"), + ] = None + base_url: Annotated[ + str | None, Field( - description="Optional display name for the group.", - examples=["Acme prod"], - title="Name", + description="Custom OpenAI-compatible base URL, if any.", title="Base Url" ), ] = None - external_entity_id: Annotated[ + model_id: Annotated[ + str | None, Field(description="Baseten model, if any.", title="Model Id") + ] = None + environment_name: Annotated[ + str | None, + Field( + description="Baseten model environment, if non-production.", + title="Environment Name", + ), + ] = None + + +class Endpoint(BaseModel): + id: Annotated[ + str, Field(description="Stable identifier for the endpoint.", title="Id") + ] + slug: Annotated[ str, Field( - description="External-system identifier for this group. Unique within the caller's org.", - examples=["cust_42"], - max_length=255, - min_length=1, - title="External Entity Id", + description="Globally-unique routing slug.", + examples=["baseten/mymodel-4"], + title="Slug", + ), + ] + created_at: Annotated[ + AwareDatetime, Field(description="Creation time, ISO 8601.", title="Created At") + ] + updated_at: Annotated[ + AwareDatetime, + Field(description="Last update time, ISO 8601.", title="Updated At"), + ] + targets: Annotated[ + list[EndpointTarget], + Field( + description="The endpoint's upstream targets. Exactly one target is supported at this time.", + title="Targets", ), ] -class LimitEnforcement(Enum): - CASCADING = "CASCADING" - INDEPENDENT = "INDEPENDENT" +class EndpointsResponse(BaseModel): + items: Annotated[ + list[Endpoint], Field(description="Items in this page.", title="Items") + ] + pagination: Annotated[ + PaginationResponse, Field(description="Pagination metadata for the page.") + ] -class LimitType(Enum): - REQUEST = "REQUEST" - TOKEN = "TOKEN" +class EndpointTargetRequest(BaseModel): + provider: Annotated[ + GatewayProvider, + Field( + description="Upstream provider for this target.", + examples=["ANTHROPIC", "OPENAI", "OPENAI_COMPATIBLE", "BASETEN"], + ), + ] + secret_id: Annotated[ + str | None, + Field( + description="Secret holding the provider credential. Required for external providers.", + examples=["3kZ9xqd"], + title="Secret Id", + ), + ] = None + target_model: Annotated[ + str | None, + Field( + description="Model name to send upstream. Required for external providers and optional for BASETEN targets.", + examples=["gpt-4o"], + title="Target Model", + ), + ] = None + base_url: Annotated[ + str | None, + Field( + description="HTTPS base URL of the upstream OpenAI-compatible server. Must not include a port. Required for and only valid with OPENAI_COMPATIBLE.", + examples=["https://my-vllm.example.com"], + title="Base Url", + ), + ] = None + model_id: Annotated[ + str | None, + Field( + description="Baseten model to route to. Required for and only valid with BASETEN.", + examples=["3kZ9xqd"], + title="Model Id", + ), + ] = None + environment_name: Annotated[ + str | None, + Field( + description="Baseten model environment to route to. Only valid with BASETEN. Omit or pass `production` to target production.", + examples=["staging"], + title="Environment Name", + ), + ] = None -class PaginationResponse(BaseModel): - has_more: Annotated[ - bool, +class CreateEndpointRequest(BaseModel): + slug: Annotated[ + str, Field( - description="Whether more items exist after this page.", title="Has More" + description="Globally-unique slug of the form '{org_prefix}/{name}'.", + examples=["baseten/mymodel-4"], + title="Slug", ), ] - cursor: Annotated[ - str | None, + targets: Annotated[ + list[EndpointTargetRequest], Field( - description="Opaque cursor to pass into the next request. Null when there is no next page.", - title="Cursor", + description="The endpoint's upstream targets. Exactly one target is supported at this time.", + examples=[ + [ + { + "environment_name": "staging", + "model_id": "3kZ9xqd", + "provider": "BASETEN", + "target_model": "custom/model-name", + } + ], + [ + { + "provider": "OPENAI", + "secret_id": "3kZ9xqd", + "target_model": "gpt-4o", + } + ], + [ + { + "base_url": "https://my-vllm.example.com", + "provider": "OPENAI_COMPATIBLE", + "secret_id": "3kZ9xqd", + "target_model": "my-model", + } + ], + ], + max_length=1, + min_length=1, + title="Targets", + ), + ] + + +class EndpointTombstone(BaseModel): + id: Annotated[ + str, Field(description="Identifier of the deleted endpoint.", title="Id") + ] + slug: Annotated[ + str, Field(description="Slug of the deleted endpoint.", title="Slug") + ] + + +class Targets(RootModel[list[EndpointTargetRequest]]): + root: Annotated[ + list[EndpointTargetRequest] | None, + Field( + description="The endpoint's upstream targets. Exactly one target is supported at this time.", + examples=[ + [ + { + "environment_name": "staging", + "model_id": "3kZ9xqd", + "provider": "BASETEN", + "target_model": "custom/model-name", + } + ], + [ + { + "provider": "OPENAI", + "secret_id": "3kZ9xqd", + "target_model": "gpt-4o", + } + ], + [ + { + "base_url": "https://my-vllm.example.com", + "provider": "OPENAI_COMPATIBLE", + "secret_id": "3kZ9xqd", + "target_model": "my-model", + } + ], + ], + max_length=1, + min_length=1, + title="Targets", ), ] = None -class RateLimitUnit(Enum): - SECOND = "SECOND" - MINUTE = "MINUTE" +class UpdateEndpointRequest(BaseModel): + targets: Annotated[ + Targets | None, + Field( + description="The endpoint's upstream targets. Exactly one target is supported at this time.", + examples=[ + [ + { + "environment_name": "staging", + "model_id": "3kZ9xqd", + "provider": "BASETEN", + "target_model": "custom/model-name", + } + ], + [ + { + "provider": "OPENAI", + "secret_id": "3kZ9xqd", + "target_model": "gpt-4o", + } + ], + [ + { + "base_url": "https://my-vllm.example.com", + "provider": "OPENAI_COMPATIBLE", + "secret_id": "3kZ9xqd", + "target_model": "my-model", + } + ], + ], + title="Targets", + ), + ] = None -class RateLimit(BaseModel): +class EffectiveRateLimit(BaseModel): type: Annotated[ LimitType, Field(description="The type of the rate limit", examples=["TOKEN", "REQUEST"]), @@ -3784,10 +4943,56 @@ class RateLimit(BaseModel): Field( description="The threshold for the rate limit", examples=[1000, 50000], - ge=1, + ge=0, title="Threshold", ), ] + source_group: Annotated[ + str, + Field( + description="ID of the group in the hierarchy this limit is anchored to.", + examples=["abc123"], + title="Source Group", + ), + ] + + +class Name2(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="Optional display name for the group.", + examples=["Acme prod"], + max_length=255, + title="Name", + ), + ] = None + + +class GroupMetadata(BaseModel): + name: Annotated[ + Name2 | None, + Field( + description="Optional display name for the group.", + examples=["Acme prod"], + title="Name", + ), + ] = None + external_entity_id: Annotated[ + str, + Field( + description="External-system identifier for this group. Unique within the caller's org.", + examples=["cust_42"], + max_length=255, + min_length=1, + title="External Entity Id", + ), + ] + + +class LimitEnforcement(Enum): + CASCADING = "CASCADING" + INDEPENDENT = "INDEPENDENT" class UsageLimitUnit(Enum): @@ -3808,7 +5013,7 @@ class UsageLimit(BaseModel): Field( description="The threshold for the usage limit", examples=[10000000], - ge=1, + ge=0, title="Threshold", ), ] @@ -3816,7 +5021,7 @@ class UsageLimit(BaseModel): class UpdateGroupMetadata(BaseModel): name: Annotated[ - Name1 | None, + Name2 | None, Field( description="Optional display name for the group.", examples=["Acme prod"], @@ -3894,6 +5099,148 @@ class RegisterAPIKeyResponse(BaseModel): ] +class Checkpoints( + RootModel[ + BasetenLatestCheckpointConfig + | BasetenNamedCheckpointConfig + | LoopsCheckpointConfig + ] +): + root: Annotated[ + BasetenLatestCheckpointConfig + | BasetenNamedCheckpointConfig + | LoopsCheckpointConfig, + Field(discriminator="typ"), + ] + + +class LoadCheckpointConfig(BaseModel): + enabled: Annotated[ + bool | None, + Field(description="Whether checkpoint loading is enabled", title="Enabled"), + ] = False + download_folder: Annotated[ + str | None, + Field( + description="Folder where checkpoints will be downloaded", + title="Download Folder", + ), + ] = "/tmp/loaded_checkpoints" + checkpoints: Annotated[ + list[Checkpoints] | None, + Field(description="List of checkpoint configurations", title="Checkpoints"), + ] = None + + +class EnvironmentGroupManageAccess(BaseModel): + is_restricted: Annotated[ + bool, + Field( + description="Whether the environment is restricted to a specific set of users.", + title="Is Restricted", + ), + ] + users: Annotated[ + list[EnvironmentGroupUser] | None, + Field( + description="Users who can manage the environment while it is restricted, including organization and team admins who always have access. Empty when the environment is unrestricted.", + title="Users", + ), + ] = None + + +class EnvironmentGroup(BaseModel): + name: Annotated[ + str, + Field( + description="Name of the environment group, matching the environment name it governs.", + examples=["staging"], + title="Name", + ), + ] + team_id: Annotated[ + str, + Field( + description="Unique identifier of the team the environment group belongs to.", + title="Team Id", + ), + ] + team_name: Annotated[ + str, + Field( + description="Name of the team the environment group belongs to.", + title="Team Name", + ), + ] + manage_access: Annotated[ + EnvironmentGroupManageAccess, + Field( + description="Settings controlling who can manage this environment group." + ), + ] + + +class EnvironmentGroups(BaseModel): + items: Annotated[ + list[EnvironmentGroup], Field(description="Items in this page.", title="Items") + ] + pagination: Annotated[ + PaginationResponse, Field(description="Pagination metadata for the page.") + ] + + +class ModelMetricDescriptor(BaseModel): + name: Annotated[str, Field(description="Canonical metric name.", title="Name")] + unit_hint: Annotated[ + ModelMetricUnitHint, Field(description="Advisory unit of the metric's values.") + ] + kind: Annotated[ + ModelMetricKind, + Field( + description="Semantic hint for how the metric behaves (GAUGE, COUNTER, HISTOGRAM)." + ), + ] + label_sets: Annotated[ + list[dict[str, str]], + Field( + description="The metric's series, in order. Each entry is the set of labels identifying one series; the value at the same index in each value set's ``values`` is that series' value. A plain metric has a single entry with no labels (`{}`). A histogram has one entry per quantile plus an average, e.g. {'quantile': '0.5'} … {'quantile': '0.99'}, {'stat': 'avg'}. A by-status metric has one entry per status, e.g. {'status': '2xx'}.", + title="Label Sets", + ), + ] + + +class GetModelMetricsResponse(BaseModel): + start_epoch_millis: Annotated[ + int, + Field(description="Start of the returned window.", title="Start Epoch Millis"), + ] + end_epoch_millis: Annotated[ + int, Field(description="End of the returned window.", title="End Epoch Millis") + ] + mode: Annotated[ModelMetricMode, Field(description="The aggregation mode used.")] + step_seconds: Annotated[ + int | None, + Field( + description="Seconds per step; populated only in SERIES mode, null otherwise.", + title="Step Seconds", + ), + ] + metric_descriptors: Annotated[ + list[ModelMetricDescriptor], + Field( + description="Descriptors for each metric; position defines the values index.", + title="Metric Descriptors", + ), + ] + metric_values: Annotated[ + list[ModelMetricValueSet], + Field( + description="Metric values per time step covering the window. In summary mode this always contains exactly one value set spanning the whole window.", + title="Metric Values", + ), + ] + + class RollingDeployConfig(BaseModel): rolling_deploy_strategy: Annotated[ RollingDeployStrategy | None, @@ -3906,10 +5253,10 @@ class RollingDeployConfig(BaseModel): int | None, Field( description="The maximum surge percentage for rolling deploys.", - examples=[10], + examples=[25], title="Max Surge Percent", ), - ] = 10 + ] = 25 max_unavailable_percent: Annotated[ int | None, Field( @@ -4268,6 +5615,12 @@ class TrainingJob(BaseModel): title="Priority", ), ] = 0 + availability_model: Annotated[ + V1AvailabilityModel | None, + Field( + description="Capacity guarantee for the job. 'dedicated' is non-preemptible on-demand capacity; 'spot' is interruptible." + ), + ] = V1AvailabilityModel.dedicated user: Annotated[ User | None, Field(description="The user who created the training job.") ] = None @@ -4429,6 +5782,10 @@ class GetTrainingJobResponse(BaseModel): training_job: Annotated[TrainingJob, Field(description="The fetched training job.")] +class UpdateTrainingJobResponse(BaseModel): + training_job: Annotated[TrainingJob, Field(description="The updated training job.")] + + class RecreateTrainingJobResponse(BaseModel): training_job: Annotated[TrainingJob, Field(description="The created training job.")] @@ -4574,6 +5931,14 @@ class LoopsRun(BaseModel): str, Field(description="The session ID this run belongs to.", title="Session Id"), ] + deployment_id: Annotated[ + str, + Field( + description="The ID of the Loops deployment the run executes on.", + title="Deployment Id", + ), + ] + name: Annotated[str, Field(description="The run's display name.", title="Name")] base_model: Annotated[ str, Field( @@ -4639,6 +6004,150 @@ class LoopsDeploymentNodeMetrics(BaseModel): ] +class APIKeyInfo(BaseModel): + prefix: Annotated[ + str, Field(description="The prefix of the API key", title="Prefix") + ] + name: Annotated[ + str | None, + Field( + description="Optional name for the API key", + examples=["my-api-key"], + title="Name", + ), + ] = None + type: Annotated[ + APIKeyCategory, + Field( + description="Type of the API key.", + examples=[ + "PERSONAL", + "WORKSPACE_EXPORT_METRICS", + "WORKSPACE_INVOKE", + "WORKSPACE_MANAGE_ALL", + ], + ), + ] + model_ids: Annotated[ + list[str] | None, + Field( + description="List of model IDs to scope the API key to, only present if type is 'WORKSPACE_EXPORT_METRICS' or 'WORKSPACE_INVOKE'", + examples=[["aaaaaaaa"]], + title="Model Ids", + ), + ] = None + team_name: Annotated[ + str | None, + Field( + description="The name of the team associated with the API key", + title="Team Name", + ), + ] = None + owner: Annotated[ + APIKeyOwner | None, + Field( + description="The user who owns the API key. Only present for personal API keys." + ), + ] = None + + +class APIKeys(BaseModel): + keys: Annotated[ + list[APIKeyInfo], + Field(description="A list of API key information", title="Keys"), + ] + + +class ModelAPI(BaseModel): + name: Annotated[ + str, + Field( + description="Identifier of the Model API. Stable, URL-safe slug used as the public identifier.", + examples=["llama-3-3-70b-instruct"], + title="Name", + ), + ] + display_name: Annotated[ + str, + Field( + description="Human-readable name of the Model API.", + examples=["Llama 3.3 70B Instruct"], + title="Display Name", + ), + ] + description: Annotated[ + str, Field(description="Description of the Model API.", title="Description") + ] + model_family: Annotated[ + str | None, + Field( + description="Family the underlying model belongs to.", + examples=["META", "DEEPSEEK", "QWEN"], + title="Model Family", + ), + ] = None + release_date: Annotated[ + date_aliased, + Field( + description="Date the Model API was made available.", title="Release Date" + ), + ] + invoke_url: Annotated[ + str, + Field( + description="Base URL for invoking the Model API. OpenAI-shaped routes (e.g. /v1/chat/completions) live underneath this host.", + examples=["https://inference.baseten.co"], + title="Invoke Url", + ), + ] + context_length: Annotated[ + int, + Field( + description="The model's context window length, in tokens.", + examples=[8192], + title="Context Length", + ), + ] + cost_per_million_input_tokens: Annotated[ + float | CostPerMillionInputTokens, + Field( + description="Cost per million input tokens, in dollars.", + examples=["0.13"], + title="Cost Per Million Input Tokens", + ), + ] + cost_per_million_output_tokens: Annotated[ + float | CostPerMillionOutputTokens, + Field( + description="Cost per million output tokens, in dollars.", + examples=["0.50"], + title="Cost Per Million Output Tokens", + ), + ] + rate_limits: Annotated[ + list[RateLimit], + Field( + description="Rate limits in effect for the workspace. Workspace-specific overrides are returned when the workspace has added this Model API and configured them; otherwise the catalog default rate limits are returned.", + title="Rate Limits", + ), + ] + org_details: Annotated[ + ModelAPIOrgDetails | None, + Field( + description="Workspace-specific state. Null when the workspace has not added this Model API." + ), + ] = None + + +class ModelAPIsResponse(BaseModel): + items: Annotated[ + list[ModelAPI], Field(description="Items in this page.", title="Items") + ] + pagination: Annotated[ + PaginationResponse, Field(description="Pagination metadata for the page.") + ] + + class BillableResource(BaseModel): id: Annotated[ str, Field(description="Unique identifier of the resource", title="Id") @@ -4692,6 +6201,20 @@ class DedicatedItem(BaseModel): title="Subtotal", ), ] + compute_cost: Annotated[ + float | ComputeCost1, + Field( + description="Compute cost in dollars for this billable resource", + title="Compute Cost", + ), + ] + surcharge_cost: Annotated[ + float | SurchargeCost1, + Field( + description="Model distribution surcharge in dollars for this billable resource", + title="Surcharge Cost", + ), + ] minutes: Annotated[ int, Field( @@ -4790,34 +6313,6 @@ class UsageSummary(BaseModel): ] = None -class EffectiveRateLimit(BaseModel): - type: Annotated[ - LimitType, - Field(description="The type of the rate limit", examples=["TOKEN", "REQUEST"]), - ] - unit: Annotated[ - RateLimitUnit, - Field(description="The unit of the rate limit", examples=["SECOND", "MINUTE"]), - ] - threshold: Annotated[ - int, - Field( - description="The threshold for the rate limit", - examples=[1000, 50000], - ge=1, - title="Threshold", - ), - ] - source_group: Annotated[ - str, - Field( - description="ID of the group in the hierarchy this limit is anchored to.", - examples=["abc123"], - title="Source Group", - ), - ] - - class EffectiveUsageLimit(BaseModel): type: Annotated[ LimitType, @@ -4832,7 +6327,7 @@ class EffectiveUsageLimit(BaseModel): Field( description="The threshold for the usage limit", examples=[10000000], - ge=1, + ge=0, title="Threshold", ), ] @@ -4869,6 +6364,7 @@ class CreateGroupRequest(BaseModel): list[ModelConfig], Field( description="Per-model rate and usage limit configuration. Defines the group's complete model set. Must be non-empty.", + min_length=1, title="Models", ), ] @@ -5194,6 +6690,7 @@ class CreateTrainingJob(BaseModel): examples=[ { "accelerator": {"accelerator": "H100", "count": 2}, + "availability_model": "spot", "cpu_count": 1, "memory": "2Gi", "node_count": 1, diff --git a/baseten/client/modelconfig/__init__.py b/baseten/client/modelconfig/__init__.py index 621e1c0..116c4b6 100644 --- a/baseten/client/modelconfig/__init__.py +++ b/baseten/client/modelconfig/__init__.py @@ -21,6 +21,7 @@ DockerAuthSettings, DockerAuthType, DockerServer, + EgressRestrictions, ExternalData, ExternalDataItem, GRPCOptions, @@ -84,6 +85,7 @@ "DockerAuthSettings", "DockerAuthType", "DockerServer", + "EgressRestrictions", "ExternalData", "ExternalDataItem", "GRPCOptions", diff --git a/baseten/client/modelconfig/_models.py b/baseten/client/modelconfig/_models.py index 9c66a10..c1c764d 100644 --- a/baseten/client/modelconfig/_models.py +++ b/baseten/client/modelconfig/_models.py @@ -102,6 +102,28 @@ class DockerServer(BaseModel): ] = None +class EgressRestrictions(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + ip_allow_list: Annotated[ + list[str] | None, + Field( + description="Allowed outbound IPv4 addresses or CIDR ranges. Use null or [] alongside an equally restrictive fqdn_allow_list to block all egress.", + examples=[["1.1.1.1", "8.8.8.8/32"]], + title="Ip Allow List", + ), + ] = None + fqdn_allow_list: Annotated[ + list[str] | None, + Field( + description="Allowed outbound fully-qualified domain names. Supports wildcards: '*' may appear anywhere in a label.", + examples=[["*.baseten.co", "huggingface.co"]], + title="Fqdn Allow List", + ), + ] = None + + class ExternalDataItem(BaseModel): model_config = ConfigDict( extra="allow", @@ -690,6 +712,12 @@ class Runtime(BaseModel): ] = None health_checks: HealthChecks | None = None remote_ssh: RemoteSSH | None = None + egress_restrictions: Annotated[ + EgressRestrictions | None, + Field( + description="Egress network restrictions for the model version. When unset, all egress is allowed (default)." + ), + ] = None truss_server_version_override: Annotated[ str | None, Field( @@ -752,7 +780,7 @@ class WeightsSource(BaseModel): source: Annotated[ str, Field( - description="URI with scheme prefix. Use hf://, s3://, gs://, azure://, r2://, or https://. For HuggingFace, use @revision suffix (e.g., hf://owner/repo@main).", + description="URI with scheme prefix. Use hf://, s3://, gs://, azure://, r2://, cw://, or https://. For HuggingFace, use @revision suffix (e.g., hf://owner/repo@main).", min_length=1, title="Source", ), diff --git a/pyproject.toml b/pyproject.toml index ab171c9..95185b9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "baseten" -version = "0.9.0" +version = "0.9.1" description = "Baseten Python SDK" readme = "README.md" license = "MIT" diff --git a/scripts/apigen/postprocess.py b/scripts/apigen/postprocess.py index fff9f8b..af07d9b 100644 --- a/scripts/apigen/postprocess.py +++ b/scripts/apigen/postprocess.py @@ -18,8 +18,8 @@ # https://github.com/koxudaxi/datamodel-code-generator/issues/2027 (closed # but the issue persists for this shape in 0.55.0). _ROOT_MODEL_BLOCK = re.compile( - r"(class \w+\(RootModel\[(?P[^\]]+)\]\):\n" - r" root: )(?P.+?)(?P = None\n)", + r"(class \w+\(RootModel\[(?P[^\n]+?)\]\):\n" + r" root: )(?P(?:(?!\nclass ).)+?)(?P = None\n)", re.DOTALL, ) diff --git a/scripts/apigen/specs/config.schema.json b/scripts/apigen/specs/config.schema.json index 54744c2..4c1be2f 100644 --- a/scripts/apigen/specs/config.schema.json +++ b/scripts/apigen/specs/config.schema.json @@ -426,6 +426,58 @@ "title": "DockerServer", "type": "object" }, + "EgressRestrictions": { + "additionalProperties": true, + "description": "Egress network restrictions for a model version.\n\nSetting both ``ip_allow_list`` and ``fqdn_allow_list`` to ``null`` or\n``[]`` blocks all outbound network egress. Omitting the\n``egress_restrictions`` block (or setting it to ``null``) preserves the\ndefault behavior of allowing all egress.", + "properties": { + "ip_allow_list": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Allowed outbound IPv4 addresses or CIDR ranges. Use null or [] alongside an equally restrictive fqdn_allow_list to block all egress.", + "examples": [ + [ + "1.1.1.1", + "8.8.8.8/32" + ] + ], + "title": "Ip Allow List" + }, + "fqdn_allow_list": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Allowed outbound fully-qualified domain names. Supports wildcards: '*' may appear anywhere in a label.", + "examples": [ + [ + "*.baseten.co", + "huggingface.co" + ] + ], + "title": "Fqdn Allow List" + } + }, + "title": "EgressRestrictions", + "type": "object" + }, "ExternalData": { "description": "[Experimental] External data is data that is not contained in the Truss folder.\n\nTypically, this will be data stored remotely. This data is guaranteed to be made\navailable under the data directory of the truss.", "items": { @@ -894,6 +946,18 @@ "remote_ssh": { "$ref": "#/$defs/RemoteSSH" }, + "egress_restrictions": { + "anyOf": [ + { + "$ref": "#/$defs/EgressRestrictions" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Egress network restrictions for the model version. When unset, all egress is allowed (default)." + }, "truss_server_version_override": { "anyOf": [ { @@ -1784,10 +1848,10 @@ }, "WeightsSource": { "additionalProperties": true, - "description": "Configuration for a weights source in the new weights API.\n\nUses a URI-based `source` field with a required scheme prefix:\n- hf:// -> HuggingFace (e.g., \"hf://meta-llama/Llama-2-7b\" or \"hf://meta-llama/Llama-2-7b@main\")\n- s3:// -> AWS S3 (e.g., \"s3://bucket/path\")\n- gs:// -> Google Cloud Storage (e.g., \"gs://bucket/path\")\n- azure:// -> Azure Blob Storage (e.g., \"azure://account/container/path\")\n- r2:// -> CloudFlare R2 Storage (e.g., \"r2://account_id.bucket/path\")\n- https:// -> Direct URL download (e.g., \"https://example.com/model.bin\")\n\nFor HuggingFace sources, you can specify a revision (branch, tag, or commit SHA)\nusing the @{rev} suffix: \"hf://owner/repo@revision\"\n\nAuthentication can be specified either:\n- Using the `auth` section (required for OIDC):\n auth:\n auth_method: AWS_OIDC\n aws_oidc_role_arn: \n aws_oidc_region: \n- Using `auth_secret_name` at the top level (or in the `auth` section)", + "description": "Configuration for a weights source in the new weights API.\n\nUses a URI-based `source` field with a required scheme prefix:\n- hf:// -> HuggingFace (e.g., \"hf://meta-llama/Llama-2-7b\" or \"hf://meta-llama/Llama-2-7b@main\")\n- s3:// -> AWS S3 (e.g., \"s3://bucket/path\")\n- gs:// -> Google Cloud Storage (e.g., \"gs://bucket/path\")\n- azure:// -> Azure Blob Storage (e.g., \"azure://account/container/path\")\n- r2:// -> CloudFlare R2 Storage (e.g., \"r2://account_id.bucket/path\")\n- cw:// -> CoreWeave AI Object Storage (e.g., \"cw://bucket/path\")\n- https:// -> Direct URL download (e.g., \"https://example.com/model.bin\")\n\nFor HuggingFace sources, you can specify a revision (branch, tag, or commit SHA)\nusing the @{rev} suffix: \"hf://owner/repo@revision\"\n\nAuthentication can be specified either:\n- Using the `auth` section (required for OIDC):\n auth:\n auth_method: AWS_OIDC\n aws_oidc_role_arn: \n aws_oidc_region: \n- Using `auth_secret_name` at the top level (or in the `auth` section)", "properties": { "source": { - "description": "URI with scheme prefix. Use hf://, s3://, gs://, azure://, r2://, or https://. For HuggingFace, use @revision suffix (e.g., hf://owner/repo@main).", + "description": "URI with scheme prefix. Use hf://, s3://, gs://, azure://, r2://, cw://, or https://. For HuggingFace, use @revision suffix (e.g., hf://owner/repo@main).", "minLength": 1, "title": "Source", "type": "string" diff --git a/scripts/apigen/specs/inference.json b/scripts/apigen/specs/inference.json index d4258a4..88b5582 100644 --- a/scripts/apigen/specs/inference.json +++ b/scripts/apigen/specs/inference.json @@ -57,7 +57,7 @@ ], "security": [ { - "ApiKeyAuth": [] + "BearerAuth": [] } ], "paths": { @@ -1023,11 +1023,10 @@ }, "components": { "securitySchemes": { - "ApiKeyAuth": { - "type": "apiKey", - "in": "header", - "name": "Authorization", - "description": "API key with the `Api-Key` prefix, e.g. `Authorization: Api-Key abcd1234.abcd1234`." + "BearerAuth": { + "type": "http", + "scheme": "bearer", + "description": "Send `Authorization: Bearer `. The legacy `Authorization: Api-Key ` scheme is also accepted." } }, "parameters": { diff --git a/scripts/apigen/specs/management.json b/scripts/apigen/specs/management.json index 19d61f9..b86dc17 100644 --- a/scripts/apigen/specs/management.json +++ b/scripts/apigen/specs/management.json @@ -11,7 +11,7 @@ ], "security": [ { - "ApiKeyAuth": [] + "BearerAuth": [] } ], "paths": { @@ -21,11 +21,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/secrets \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/secrets\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -46,14 +46,14 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/secrets \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my_secret\",\n \"value\": \"my_secret_value\"\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my_secret\",\n \"value\": \"my_secret_value\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/secrets\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my_secret', 'value': 'my_secret_value'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my_secret', 'value': 'my_secret_value'}\n)\n\nprint(response.text)" } ], - "description": "Creates or updates a secret by name. Scoped to the caller's primary team \u2014 use the team-scoped variant to target a specific team.", + "description": "Creates or updates a secret by name. Scoped to the caller's primary team; use the team-scoped variant to target a specific team.", "requestBody": { "content": { "application/json": { @@ -84,11 +84,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/secrets/{secret_name} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/secrets/{secret_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/secrets/{secret_name}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/secrets/{secret_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes a secret by name in the specified team, or in the caller's organization default team when no team is specified.", @@ -117,11 +117,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/secrets \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/secrets\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -147,11 +147,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/secrets \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my_secret\",\n \"value\": \"my_secret_value\"\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my_secret\",\n \"value\": \"my_secret_value\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/secrets\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my_secret', 'value': 'my_secret_value'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my_secret', 'value': 'my_secret_value'}\n)\n\nprint(response.text)" } ], "description": "Creates a new secret or updates an existing secret if one with the provided name already exists. The name and creation date of the created or updated secret is returned. This secret belongs to the specified team", @@ -185,11 +185,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/teams/{team_id}/secrets/{secret_name} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/teams/{team_id}/secrets/{secret_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/secrets/{secret_name}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/secrets/{secret_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes a secret by name in the specified team, or in the caller's organization default team when no team is specified.", @@ -215,27 +215,27 @@ } ] }, - "/v1/teams": { + "/v1/environment_groups": { "get": { - "summary": "Lists all teams", + "summary": "Lists environment groups", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/environment_groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/environment_groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Returns a list of all teams the authenticated user has access to.", + "description": "Lists environment groups. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TeamsV1" + "$ref": "#/components/schemas/EnvironmentGroupsV1" } } } @@ -243,53 +243,68 @@ } } }, - "/v1/instance_types": { + "/v1/environment_groups/{env_name}": { "get": { - "summary": "Gets all available instance types", + "summary": "Gets an environment group by name", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/instance_types \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/instance_types\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], + "description": "Gets a single environment group by name. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InstanceTypesV1" + "$ref": "#/components/schemas/EnvironmentGroupV1" } } } } } - } - }, - "/v1/instance_type_prices": { - "get": { - "summary": "Gets prices for available instance types.", + }, + "parameters": [ + { + "$ref": "#/components/parameters/env_name" + } + ], + "patch": { + "summary": "Updates an environment group's restriction settings", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/instance_type_prices \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"manage_access\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/instance_type_prices\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'manage_access': None}\n)\n\nprint(response.text)" } ], + "description": "Sets whether the environment is restricted and replaces the list of users granted manage access. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateEnvironmentGroupRequestV1" + } + } + }, + "required": true + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InstanceTypePricesV1" + "$ref": "#/components/schemas/EnvironmentGroupV1" } } } @@ -297,87 +312,92 @@ } } }, - "/v1/prepare_model_upload": { - "post": { - "summary": "Validates a model push payload and issues upload credentials", + "/v1/teams/{team_id}/environment_groups": { + "get": { + "summary": "Lists environment groups", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/prepare_model_upload \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"deployment\": {\n \"config\": null,\n \"raw_config\": null,\n \"user_env\": null,\n \"environment_name\": null,\n \"preserve_env_instance_type\": null,\n \"deploy_timeout_minutes\": null,\n \"deployment_name\": null,\n \"labels\": null\n },\n \"name\": null,\n \"team_id\": null,\n \"model_id\": null,\n \"dry_run\": null,\n \"is_development\": null\n}'" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/environment_groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/prepare_model_upload\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'deployment': {'config': None, 'raw_config': None, 'user_env': None, 'environment_name': None, 'preserve_env_instance_type': None, 'deploy_timeout_minutes': None, 'deployment_name': None, 'labels': None}, 'name': None, 'team_id': None, 'model_id': None, 'dry_run': None, 'is_development': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/environment_groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PrepareModelUploadRequestV1" - } - } - }, - "required": true - }, + "description": "Lists environment groups. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PrepareModelUploadResponseV1" + "$ref": "#/components/schemas/EnvironmentGroupsV1" } } } } } - } + }, + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + } + ] }, - "/v1/models": { + "/v1/teams/{team_id}/environment_groups/{env_name}": { "get": { - "summary": "Gets all models", + "summary": "Gets an environment group by name", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], + "description": "Gets a single environment group by name. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ModelsV1" + "$ref": "#/components/schemas/EnvironmentGroupV1" } } } } } }, - "post": { - "summary": "Creates a new model from a source", + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + }, + { + "$ref": "#/components/parameters/env_name" + } + ], + "patch": { + "summary": "Updates an environment group's restriction settings", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/teams/{team_id}/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"manage_access\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'manage_access': None}\n)\n\nprint(response.text)" } ], - "description": "Creates a new model in the caller's organization. The `source` field selects how the model is constructed (currently: `library_listing` \u2014 fork an accessible listing from `GET /v1/library_models`). The deployment isn't instantly ready \u2014 poll GET endpoint until status is ACTIVE.", + "description": "Sets whether the environment is restricted and replaces the list of users granted manage access. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateModelRequestV1" + "$ref": "#/components/schemas/UpdateEnvironmentGroupRequestV1" } } }, @@ -389,7 +409,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreatedModelDeploymentV1" + "$ref": "#/components/schemas/EnvironmentGroupV1" } } } @@ -397,67 +417,47 @@ } } }, - "/v1/teams/{team_id}/models": { + "/v1/teams": { "get": { - "summary": "Gets all models", + "summary": "Lists all teams", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/models \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/models\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ModelsV1" + "description": "Returns a list of all teams the authenticated user has access to.", + "parameters": [ + { + "name": "name", + "in": "query", + "required": false, + "description": "When set, returns only the team with this exact name, if any.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "default": null, + "title": "Name" } } - } - }, - "parameters": [ - { - "$ref": "#/components/parameters/team_id" - } - ], - "post": { - "summary": "Creates a new model from a source", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/models \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" - }, - { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/models\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" - } ], - "description": "Creates a new model in the caller's organization. The `source` field selects how the model is constructed (currently: `library_listing` \u2014 fork an accessible listing from `GET /v1/library_models`). The deployment isn't instantly ready \u2014 poll GET endpoint until status is ACTIVE.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateModelRequestV1" - } - } - }, - "required": true - }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreatedModelDeploymentV1" + "$ref": "#/components/schemas/TeamsV1" } } } @@ -465,26 +465,27 @@ } } }, - "/v1/models/{model_id}": { - "delete": { - "summary": "Deletes a model by ID", + "/v1/teams/{team_id}": { + "get": { + "summary": "Gets a team by ID", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/models/{model_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], + "description": "Returns a team the authenticated user has access to.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ModelTombstoneV1" + "$ref": "#/components/schemas/TeamV1" } } } @@ -493,19 +494,21 @@ }, "parameters": [ { - "$ref": "#/components/parameters/model_id" + "$ref": "#/components/parameters/team_id" } - ], + ] + }, + "/v1/instance_types": { "get": { - "summary": "Gets a model by ID", + "summary": "Gets all available instance types", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/instance_types \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/instance_types\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -514,7 +517,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ModelV1" + "$ref": "#/components/schemas/InstanceTypesV1" } } } @@ -522,54 +525,51 @@ } } }, - "/v1/models/{model_id}/deployments": { + "/v1/loops/user_config": { "get": { - "summary": "Gets all deployments of a model", + "summary": "Gets the caller's Loops user config", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/user_config \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/user_config\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], + "description": "Returns the caller's Loops user config (per-user accelerator priorities). Null fields mean 'inherit the org-level allowlist'.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeploymentsV1" + "$ref": "#/components/schemas/GetLoopsUserConfigResponseV1" } } } } } }, - "parameters": [ - { - "$ref": "#/components/parameters/model_id" - } - ], - "post": { - "summary": "Adds a new deployment to a model", + "patch": { + "summary": "Patches the caller's Loops user config", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/loops/user_config \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"trainer_accelerator_priority\": [\n \"H100\",\n \"H200\"\n ],\n \"sampler_accelerator_priority\": [\n \"H100\",\n \"H200\"\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/user_config\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'trainer_accelerator_priority': ['H100', 'H200'], 'sampler_accelerator_priority': ['H100', 'H200']}\n)\n\nprint(response.text)" } ], + "description": "Updates the caller's Loops user config using JSON Merge Patch (RFC 7396) semantics per field: omit a field to leave it unchanged, send null to clear (inherit the org-level allowlist), or send a list to set the allowlist. Empty lists are rejected.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateModelDeploymentRequestV1" + "$ref": "#/components/schemas/PatchLoopsUserConfigRequestV1" } } }, @@ -581,7 +581,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreatedModelDeploymentV1" + "$ref": "#/components/schemas/PatchLoopsUserConfigResponseV1" } } } @@ -589,153 +589,134 @@ } } }, - "/v1/models/{model_id}/deployments/development": { + "/v1/instance_type_prices": { "get": { - "summary": "Gets a model's development deployment", + "summary": "Gets prices for available instance types", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/instance_type_prices \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/instance_type_prices\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Gets a model's development deployment and returns the deployment.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeploymentV1" + "$ref": "#/components/schemas/InstanceTypePricesV1" } } } } } - }, - "parameters": [ - { - "$ref": "#/components/parameters/model_id" - } - ] + } }, - "/v1/models/{model_id}/deployments/production": { - "get": { - "summary": "Gets a model's production deployment", + "/v1/prepare_model_upload": { + "post": { + "summary": "Validates a model push payload and issues upload credentials", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/prepare_model_upload \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"deployment\": {\n \"config\": null,\n \"raw_config\": null,\n \"user_env\": null,\n \"environment_name\": null,\n \"deploy_timeout_minutes\": null,\n \"deployment_name\": null,\n \"labels\": null\n },\n \"name\": null,\n \"team_id\": null,\n \"model_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/prepare_model_upload\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'deployment': {'config': None, 'raw_config': None, 'user_env': None, 'environment_name': None, 'deploy_timeout_minutes': None, 'deployment_name': None, 'labels': None}, 'name': None, 'team_id': None, 'model_id': None}\n)\n\nprint(response.text)" } ], - "description": "Gets a model's production deployment and returns the deployment.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PrepareModelUploadRequestV1" + } + } + }, + "required": true + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeploymentV1" + "$ref": "#/components/schemas/PrepareModelUploadResponseV1" } } } } } - }, - "parameters": [ - { - "$ref": "#/components/parameters/model_id" - } - ] + } }, - "/v1/models/{model_id}/deployments/{deployment_id}": { - "delete": { - "summary": "Deletes a model's deployment by ID", + "/v1/models": { + "get": { + "summary": "Gets all models", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Deletes a model's deployment by ID and returns the tombstone of the deployment.", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeploymentTombstoneV1" + "parameters": [ + { + "name": "name", + "in": "query", + "required": false, + "description": "When set, returns only models with this exact name, if any. On a team-scoped route this matches at most one model; on the org-wide route it may match models in multiple teams, since names are unique only within a team.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "default": null, + "title": "Name" } } - } - }, - "parameters": [ - { - "$ref": "#/components/parameters/model_id" - }, - { - "$ref": "#/components/parameters/deployment_id" - } - ], - "get": { - "summary": "Gets a model's deployment by ID", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" - }, - { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } ], - "description": "Gets a model's deployment by ID and returns the deployment.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeploymentV1" + "$ref": "#/components/schemas/ModelsV1" } } } } } - } - }, - "/v1/models/{model_id}/deployments/development/autoscaling_settings": { - "patch": { - "summary": "Updates a development deployment's autoscaling settings", + }, + "post": { + "summary": "Creates a new model from a source", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/autoscaling_settings \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 2.0\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 2.0}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" } ], - "description": "Updates a development deployment's autoscaling settings and returns the update status.", + "description": "Creates a new model in the caller's organization. The `source` field selects how the model is constructed (currently `library_listing`, which forks an accessible listing from `GET /v1/library_models`). The deployment isn't instantly ready; poll the GET endpoint until status is ACTIVE.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1" + "$ref": "#/components/schemas/CreateModelRequestV1" } } }, @@ -747,50 +728,54 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateAutoscalingSettingsResponseV1" + "$ref": "#/components/schemas/CreatedModelDeploymentV1" } } } } } - }, - "parameters": [ - { - "$ref": "#/components/parameters/model_id" - } - ] + } }, - "/v1/models/{model_id}/deployments/production/autoscaling_settings": { - "patch": { - "summary": "Updates a production deployment's autoscaling settings", + "/v1/teams/{team_id}/models": { + "get": { + "summary": "Gets all models", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production/autoscaling_settings \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 2.0\n}'" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 2.0}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Updates a production deployment's autoscaling settings and returns the update status.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1" - } + "parameters": [ + { + "name": "name", + "in": "query", + "required": false, + "description": "When set, returns only models with this exact name, if any. On a team-scoped route this matches at most one model; on the org-wide route it may match models in multiple teams, since names are unique only within a team.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" } - }, - "required": true - }, + } + ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateAutoscalingSettingsResponseV1" + "$ref": "#/components/schemas/ModelsV1" } } } @@ -799,29 +784,27 @@ }, "parameters": [ { - "$ref": "#/components/parameters/model_id" + "$ref": "#/components/parameters/team_id" } - ] - }, - "/v1/models/{model_id}/deployments/{deployment_id}/autoscaling_settings": { - "patch": { - "summary": "Updates a deployment's autoscaling settings", + ], + "post": { + "summary": "Creates a new model from a source", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/autoscaling_settings \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 2.0\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 2.0}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" } ], - "description": "Updates a deployment's autoscaling settings and returns the update status.", + "description": "Creates a new model in the caller's organization. The `source` field selects how the model is constructed (currently `library_listing`, which forks an accessible listing from `GET /v1/library_models`). The deployment isn't instantly ready; poll the GET endpoint until status is ACTIVE.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1" + "$ref": "#/components/schemas/CreateModelRequestV1" } } }, @@ -833,7 +816,34 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateAutoscalingSettingsResponseV1" + "$ref": "#/components/schemas/CreatedModelDeploymentV1" + } + } + } + } + } + } + }, + "/v1/models/{model_id}": { + "delete": { + "summary": "Deletes a model by ID", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/models/{model_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModelTombstoneV1" } } } @@ -843,43 +853,74 @@ "parameters": [ { "$ref": "#/components/parameters/model_id" - }, - { - "$ref": "#/components/parameters/deployment_id" } - ] - }, - "/v1/models/{model_id}/deployments/development/promote": { - "post": { - "summary": "Promotes a development deployment to production", + ], + "get": { + "summary": "Gets a model by ID", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/promote \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_production\": true,\n \"preserve_env_instance_type\": true\n}'" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/promote\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_production': True, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Creates a new production deployment from the development deployment, the currently building deployment is returned.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PromoteRequestV1" + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModelV1" + } } } + } + } + } + }, + "/v1/models/{model_id}/deployments": { + "get": { + "summary": "Gets all deployments of a model", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, - "required": true - }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "parameters": [ + { + "name": "name", + "in": "query", + "required": false, + "description": "When set, returns only the deployment with this exact name, if any.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + } + } + ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeploymentV1" + "$ref": "#/components/schemas/DeploymentsV1" } } } @@ -890,27 +931,24 @@ { "$ref": "#/components/parameters/model_id" } - ] - }, - "/v1/models/{model_id}/deployments/{deployment_id}/promote": { + ], "post": { - "summary": "Promotes a deployment to production", + "summary": "Adds a new deployment to a model", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/promote \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_production\": true,\n \"preserve_env_instance_type\": true\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/promote\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_production': True, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" } ], - "description": "Promotes an existing deployment to production and returns the same deployment.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PromoteRequestV1" + "$ref": "#/components/schemas/CreateModelDeploymentRequestV1" } } }, @@ -922,43 +960,35 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeploymentV1" + "$ref": "#/components/schemas/CreatedModelDeploymentV1" } } } } } - }, - "parameters": [ - { - "$ref": "#/components/parameters/model_id" - }, - { - "$ref": "#/components/parameters/deployment_id" - } - ] + } }, - "/v1/models/{model_id}/deployments/development/activate": { - "post": { - "summary": "Activates a development deployment", + "/v1/models/{model_id}/deployments/development": { + "get": { + "summary": "Gets a model's development deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/activate \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/activate\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Activates an inactive development deployment and returns the activation status.", + "description": "Gets a model's development deployment and returns the deployment.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ActivateResponseV1" + "$ref": "#/components/schemas/DeploymentV1" } } } @@ -971,27 +1001,27 @@ } ] }, - "/v1/models/{model_id}/deployments/production/activate": { - "post": { - "summary": "Activates a production deployment", + "/v1/models/{model_id}/deployments/production": { + "get": { + "summary": "Gets a model's production deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production/activate \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production/activate\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Activates an inactive production deployment and returns the activation status.", + "description": "Gets a model's production deployment and returns the deployment.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ActivateResponseV1" + "$ref": "#/components/schemas/DeploymentV1" } } } @@ -1004,27 +1034,27 @@ } ] }, - "/v1/models/{model_id}/deployments/{deployment_id}/activate": { - "post": { - "summary": "Activates a deployment", + "/v1/models/{model_id}/deployments/{deployment_id}": { + "delete": { + "summary": "Deletes a model's deployment by ID", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/activate \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/activate\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Activates an inactive deployment and returns the activation status.", + "description": "Deletes a model's deployment by ID and returns the tombstone of the deployment.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ActivateResponseV1" + "$ref": "#/components/schemas/DeploymentTombstoneV1" } } } @@ -1038,62 +1068,65 @@ { "$ref": "#/components/parameters/deployment_id" } - ] - }, - "/v1/models/{model_id}/deployments/development/deactivate": { - "post": { - "summary": "Deactivates a development deployment", + ], + "get": { + "summary": "Gets a model's deployment by ID", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/deactivate \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/deactivate\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Deactivates a development deployment and returns the deactivation status.", + "description": "Gets a model's deployment by ID and returns the deployment.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeactivateResponseV1" + "$ref": "#/components/schemas/DeploymentV1" } } } } } - }, - "parameters": [ - { - "$ref": "#/components/parameters/model_id" - } - ] + } }, - "/v1/models/{model_id}/deployments/production/deactivate": { - "post": { - "summary": "Deactivates a production deployment", + "/v1/models/{model_id}/deployments/development/autoscaling_settings": { + "patch": { + "summary": "Updates a development deployment's autoscaling settings", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production/deactivate \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 20\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production/deactivate\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 20}\n)\n\nprint(response.text)" } ], - "description": "Deactivates a production deployment and returns the deactivation status.", + "description": "Updates a development deployment's autoscaling settings and returns the update status.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1" + } + } + }, + "required": true + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeactivateResponseV1" + "$ref": "#/components/schemas/UpdateAutoscalingSettingsResponseV1" } } } @@ -1106,27 +1139,37 @@ } ] }, - "/v1/models/{model_id}/deployments/{deployment_id}/deactivate": { - "post": { - "summary": "Deactivates a deployment", + "/v1/models/{model_id}/deployments/production/autoscaling_settings": { + "patch": { + "summary": "Updates a production deployment's autoscaling settings", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/deactivate \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 20\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 20}\n)\n\nprint(response.text)" } ], - "description": "Deactivates a deployment and returns the deactivation status.", + "description": "Updates a production deployment's autoscaling settings and returns the update status.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1" + } + } + }, + "required": true + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeactivateResponseV1" + "$ref": "#/components/schemas/UpdateAutoscalingSettingsResponseV1" } } } @@ -1136,33 +1179,40 @@ "parameters": [ { "$ref": "#/components/parameters/model_id" - }, - { - "$ref": "#/components/parameters/deployment_id" } ] }, - "/v1/models/{model_id}/deployments/development/retry": { - "post": { - "summary": "Retries a failed development deployment", + "/v1/models/{model_id}/deployments/{deployment_id}/autoscaling_settings": { + "patch": { + "summary": "Updates a deployment's autoscaling settings", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/retry \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 20\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/retry\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 20}\n)\n\nprint(response.text)" } ], - "description": "Retries a failed development deployment and returns the retry status and updated deployment.", - "responses": { - "200": { + "description": "Updates a deployment's autoscaling settings and returns the update status.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1" + } + } + }, + "required": true + }, + "responses": { + "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RetryDeploymentResponseV1" + "$ref": "#/components/schemas/UpdateAutoscalingSettingsResponseV1" } } } @@ -1172,30 +1222,43 @@ "parameters": [ { "$ref": "#/components/parameters/model_id" + }, + { + "$ref": "#/components/parameters/deployment_id" } ] }, - "/v1/models/{model_id}/deployments/production/retry": { + "/v1/models/{model_id}/deployments/development/promote": { "post": { - "summary": "Retries a failed production deployment", + "summary": "Promotes a development deployment to production", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production/retry \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_production\": true,\n \"preserve_env_instance_type\": true\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production/retry\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_production': True, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" } ], - "description": "Retries a failed production deployment and returns the retry status and updated deployment.", + "description": "Creates a new production deployment from the development deployment and returns the deployment that is building.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PromoteRequestV1" + } + } + }, + "required": true + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RetryDeploymentResponseV1" + "$ref": "#/components/schemas/DeploymentV1" } } } @@ -1208,27 +1271,37 @@ } ] }, - "/v1/models/{model_id}/deployments/{deployment_id}/retry": { + "/v1/models/{model_id}/deployments/{deployment_id}/promote": { "post": { - "summary": "Retries a failed deployment", + "summary": "Promotes a deployment to production", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/retry \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_production\": true,\n \"preserve_env_instance_type\": true\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/retry\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_production': True, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" } ], - "description": "Retries a failed deployment and returns the retry status and updated deployment.", + "description": "Promotes an existing deployment to production and returns the same deployment.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PromoteRequestV1" + } + } + }, + "required": true + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RetryDeploymentResponseV1" + "$ref": "#/components/schemas/DeploymentV1" } } } @@ -1244,27 +1317,27 @@ } ] }, - "/v1/models/{model_id}/deployments/{deployment_id}/download": { - "get": { - "summary": "Gets a presigned download URL for a deployment's truss", + "/v1/models/{model_id}/deployments/development/activate": { + "post": { + "summary": "Activates a development deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/download \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/download\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Gets a presigned URL to download the truss tar file for a deployment.", + "description": "Activates an inactive development deployment and returns the activation status.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DownloadDeploymentResponseV1" + "$ref": "#/components/schemas/ActivateResponseV1" } } } @@ -1274,45 +1347,30 @@ "parameters": [ { "$ref": "#/components/parameters/model_id" - }, - { - "$ref": "#/components/parameters/deployment_id" } ] }, - "/v1/models/{model_id}/deployments/{deployment_id}/config": { - "get": { - "summary": "Gets a deployment's config", + "/v1/models/{model_id}/deployments/production/activate": { + "post": { + "summary": "Activates a production deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/config \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/config\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } - ], - "description": "Returns the deployment's config. `output_format` query param picks the shape: 'raw' (config.yaml text), 'parsed' (dict with defaults), or 'both' (default).", - "parameters": [ - { - "name": "output_format", - "in": "query", - "required": false, - "description": "'raw': verbatim config.yaml with comments \u2014 not available for deployments created before 2026-04-30. 'parsed': dict with server-side defaults applied \u2014 always available. 'both': both fields populated.", - "schema": { - "$ref": "#/components/schemas/DeploymentConfigOutputFormat", - "default": "both" - } + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], + "description": "Activates an inactive production deployment and returns the activation status.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeploymentConfigResponseV1" + "$ref": "#/components/schemas/ActivateResponseV1" } } } @@ -1322,108 +1380,30 @@ "parameters": [ { "$ref": "#/components/parameters/model_id" - }, - { - "$ref": "#/components/parameters/deployment_id" } ] }, - "/v1/models/{model_id}/deployments/{deployment_id}/logs": { - "get": { - "summary": "Gets the logs for a model deployment.", + "/v1/models/{model_id}/deployments/{deployment_id}/activate": { + "post": { + "summary": "Activates a deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } - ], - "description": "Gets all the logs for a model deployment in the given time range.", - "parameters": [ - { - "name": "start_epoch_millis", - "in": "query", - "required": false, - "description": "Epoch millis timestamp to start fetching logs", - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Start Epoch Millis" - } - }, - { - "name": "end_epoch_millis", - "in": "query", - "required": false, - "description": "Epoch millis timestamp to end fetching logs", - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "End Epoch Millis" - } - }, - { - "name": "direction", - "in": "query", - "required": false, - "description": "Sort order for logs", - "schema": { - "anyOf": [ - { - "$ref": "#/components/schemas/SortOrderV1" - }, - { - "type": "null" - } - ], - "default": null - } - }, - { - "name": "limit", - "in": "query", - "required": false, - "description": "Limit of logs to fetch in a single request", - "schema": { - "anyOf": [ - { - "maximum": 1000, - "minimum": 1, - "type": "integer" - }, - { - "type": "null" - } - ], - "default": 500, - "title": "Limit" - } + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], + "description": "Activates an inactive deployment and returns the activation status.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetLogsResponseV1" + "$ref": "#/components/schemas/ActivateResponseV1" } } } @@ -1437,67 +1417,62 @@ { "$ref": "#/components/parameters/deployment_id" } - ], + ] + }, + "/v1/models/{model_id}/deployments/development/deactivate": { "post": { - "summary": "Gets the logs for a model deployment (deprecated; use GET).", + "summary": "Deactivates a development deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"start_epoch_millis\": null,\n \"end_epoch_millis\": null,\n \"direction\": null,\n \"limit\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Use the GET form on this path instead.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetDeploymentLogsRequestV1" - } - } - }, - "required": true - }, + "description": "Deactivates a development deployment and returns the deactivation status.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetLogsResponseV1" + "$ref": "#/components/schemas/DeactivateResponseV1" } } } } - }, - "x-stability": "deprecated", - "deprecated": true - } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/model_id" + } + ] }, - "/v1/models/{model_id}/deployments/{deployment_id}/replicas/{replica_id}": { - "delete": { - "summary": "Terminates a replica in a deployment", + "/v1/models/{model_id}/deployments/production/deactivate": { + "post": { + "summary": "Deactivates a production deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/replicas/{replica_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/replicas/{replica_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Terminates a deployment replica and returns the termination status.", + "description": "Deactivates a production deployment and returns the deactivation status.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TerminateReplicaResponseV1" + "$ref": "#/components/schemas/DeactivateResponseV1" } } } @@ -1507,46 +1482,30 @@ "parameters": [ { "$ref": "#/components/parameters/model_id" - }, - { - "$ref": "#/components/parameters/deployment_id" - }, - { - "$ref": "#/components/parameters/replica_id" } ] }, - "/v1/models/{model_id}/deployments/{deployment_id}/ssh/sign": { + "/v1/models/{model_id}/deployments/{deployment_id}/deactivate": { "post": { - "summary": "Sign an SSH certificate for an inference model.", + "summary": "Deactivates a deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/ssh/sign \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"public_key\": null,\n \"replica_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/ssh/sign\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'public_key': None, 'replica_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Signs a short-lived SSH certificate granting access to a running inference model pod. Returns the signed SSH certificate, a JWT token for SSH proxy authentication, the proxy address to connect through, and the certificate expiry time.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SignSSHCertificateRequestV1" - } - } - }, - "required": true - }, + "description": "Deactivates a deployment and returns the deactivation status.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SignSSHCertificateResponseV1" + "$ref": "#/components/schemas/DeactivateResponseV1" } } } @@ -1562,27 +1521,27 @@ } ] }, - "/v1/models/{model_id}/environments": { - "get": { - "summary": "Get all environments", + "/v1/models/{model_id}/deployments/development/retry": { + "post": { + "summary": "Retries a failed development deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/environments \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/retry \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/retry\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Gets all environments for a given model", + "description": "Retries a failed development deployment and returns the retry status and updated deployment.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EnvironmentsV1" + "$ref": "#/components/schemas/RetryDeploymentResponseV1" } } } @@ -1593,65 +1552,29 @@ { "$ref": "#/components/parameters/model_id" } - ], + ] + }, + "/v1/models/{model_id}/deployments/production/retry": { "post": { - "summary": "Create an environment", + "summary": "Retries a failed production deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"staging\",\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 3,\n \"max_replica\": 2,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 60,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": true,\n \"rolling_deploy_config\": null\n }\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production/retry \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'staging', 'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 3, 'max_replica': 2, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 60, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': True, 'rolling_deploy_config': None}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production/retry\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Creates an environment for the specified model and returns the environment.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateEnvironmentRequestV1" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnvironmentV1" - } - } - } - } - } - } - }, - "/v1/models/{model_id}/environments/{env_name}": { - "get": { - "summary": "Get an environment's details", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" - }, - { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } - ], - "description": "Gets an environment's details and returns the environment.", + "description": "Retries a failed production deployment and returns the retry status and updated deployment.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EnvironmentV1" + "$ref": "#/components/schemas/RetryDeploymentResponseV1" } } } @@ -1661,69 +1584,30 @@ "parameters": [ { "$ref": "#/components/parameters/model_id" - }, - { - "$ref": "#/components/parameters/env_name" - } - ], - "patch": { - "summary": "Update an environment's settings", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 3,\n \"max_replica\": 2,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 60,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n }\n}'" - }, - { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 3, 'max_replica': 2, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 60, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': None, 'rolling_deploy_config': None}}\n)\n\nprint(response.text)" - } - ], - "description": "Asynchronously updates an environment's settings. Poll the GET endpoint for the applied state.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateEnvironmentRequestV1" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateAutoscalingSettingsResponseV1" - } - } - } - } } - } + ] }, - "/v1/models/{model_id}/environments/{env_name}/activate": { + "/v1/models/{model_id}/deployments/{deployment_id}/retry": { "post": { - "summary": "Activates a deployment associated with an environment", + "summary": "Retries a failed deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/activate \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/retry \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/activate\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/retry\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Activates an inactive deployment associated with an environment and returns the activation status.", + "description": "Retries a failed deployment and returns the retry status and updated deployment.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ActivateResponseV1" + "$ref": "#/components/schemas/RetryDeploymentResponseV1" } } } @@ -1735,31 +1619,31 @@ "$ref": "#/components/parameters/model_id" }, { - "$ref": "#/components/parameters/env_name" + "$ref": "#/components/parameters/deployment_id" } ] }, - "/v1/models/{model_id}/environments/{env_name}/deactivate": { - "post": { - "summary": "Deactivates a deployment associated with an environment", + "/v1/models/{model_id}/deployments/{deployment_id}/download": { + "get": { + "summary": "Gets a presigned download URL for a deployment's truss", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/deactivate \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/download \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/deactivate\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/download\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Deactivates a deployment associated with an environment and returns the deactivation status.", + "description": "Gets a presigned URL to download the truss tar file for a deployment.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeactivateResponseV1" + "$ref": "#/components/schemas/DownloadDeploymentResponseV1" } } } @@ -1771,41 +1655,43 @@ "$ref": "#/components/parameters/model_id" }, { - "$ref": "#/components/parameters/env_name" + "$ref": "#/components/parameters/deployment_id" } ] }, - "/v1/models/{model_id}/environments/{env_name}/promote": { - "post": { - "summary": "Promotes a deployment to an environment", + "/v1/models/{model_id}/deployments/{deployment_id}/config": { + "get": { + "summary": "Gets a deployment's config", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/promote \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_deployment\": true,\n \"deployment_id\": null,\n \"preserve_env_instance_type\": true\n}'" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/config \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/promote\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_deployment': True, 'deployment_id': None, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/config\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Promotes an existing deployment to an environment and returns the promoted deployment.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PromoteToEnvironmentRequestV1" - } + "description": "Returns the deployment's config. `output_format` query param picks the shape: 'raw' (config.yaml text), 'parsed' (dict with defaults), or 'both' (default).", + "parameters": [ + { + "name": "output_format", + "in": "query", + "required": false, + "description": "'raw': verbatim config.yaml with comments (not available for deployments created before 2026-04-30). 'parsed': dict with server-side defaults applied (always available). 'both': both fields populated.", + "schema": { + "$ref": "#/components/schemas/DeploymentConfigOutputFormat", + "default": "both" } - }, - "required": true - }, + } + ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeploymentV1" + "$ref": "#/components/schemas/DeploymentConfigResponseV1" } } } @@ -1817,175 +1703,227 @@ "$ref": "#/components/parameters/model_id" }, { - "$ref": "#/components/parameters/env_name" + "$ref": "#/components/parameters/deployment_id" } ] }, - "/v1/models/{model_id}/environments/{env_name}/cancel_promotion": { - "post": { - "summary": "Cancels a promotion to an environment", + "/v1/models/{model_id}/deployments/{deployment_id}/logs": { + "get": { + "summary": "Gets the logs for a model deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/cancel_promotion \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/cancel_promotion\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Cancels an ongoing promotion to an environment and returns the cancellation status.", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CancelPromotionResponseV1" + "description": "Gets all the logs for a model deployment in the given time range, which defaults to the last 30 minutes. A failed or older deployment may only have logs from before that window; pass `start_epoch_millis` to widen it back to the build/deploy time.", + "parameters": [ + { + "name": "start_epoch_millis", + "in": "query", + "required": false, + "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" } - } + ], + "default": null, + "title": "Start Epoch Millis" } - } - } - }, - "parameters": [ - { - "$ref": "#/components/parameters/model_id" - }, - { - "$ref": "#/components/parameters/env_name" - } - ] - }, - "/v1/models/{model_id}/environments/{env_name}/pause_promotion": { - "post": { - "summary": "Pauses a rolling promotion", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/pause_promotion \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" }, { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/pause_promotion\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } - ], - "description": "Pauses an in-progress rolling promotion after the current step completes. No further scaling changes are made until resumed.", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SignalPromotionResponseV1" + "name": "end_epoch_millis", + "in": "query", + "required": false, + "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" } - } + ], + "default": null, + "title": "End Epoch Millis" } - } - } - }, - "parameters": [ - { - "$ref": "#/components/parameters/model_id" - }, - { - "$ref": "#/components/parameters/env_name" - } - ] - }, - "/v1/models/{model_id}/environments/{env_name}/resume_promotion": { - "post": { - "summary": "Resumes a paused rolling promotion", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/resume_promotion \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" }, { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/resume_promotion\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } - ], - "description": "Resumes a paused rolling promotion, continuing from where it was paused.", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SignalPromotionResponseV1" + "name": "direction", + "in": "query", + "required": false, + "description": "Sort order for logs", + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/SortOrderV1" + }, + { + "type": "null" } - } + ], + "default": null } - } - } - }, - "parameters": [ - { - "$ref": "#/components/parameters/model_id" - }, - { - "$ref": "#/components/parameters/env_name" - } - ] - }, - "/v1/models/{model_id}/environments/{env_name}/force_cancel_promotion": { - "post": { - "summary": "Force cancels a rolling promotion", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/force_cancel_promotion \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" }, { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/force_cancel_promotion\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } - ], - "description": "Immediately cancels an in-progress rolling promotion and triggers rollback to the previous version.", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SignalPromotionResponseV1" + "name": "limit", + "in": "query", + "required": false, + "description": "Limit of logs to fetch in a single request", + "schema": { + "anyOf": [ + { + "maximum": 1000, + "minimum": 1, + "type": "integer" + }, + { + "type": "null" } - } + ], + "default": 500, + "title": "Limit" } - } - } - }, - "parameters": [ - { - "$ref": "#/components/parameters/model_id" - }, - { - "$ref": "#/components/parameters/env_name" - } - ] - }, - "/v1/models/{model_id}/environments/{env_name}/force_roll_forward_promotion": { - "post": { - "summary": "Force rolls forward a rolling promotion", - "x-codeSamples": [ + }, { - "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/force_roll_forward_promotion \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "name": "min_level", + "in": "query", + "required": false, + "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level.", + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/LogLevelV1" + }, + { + "type": "null" + } + ], + "default": null + } }, { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/force_roll_forward_promotion\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "name": "replica", + "in": "query", + "required": false, + "description": "Only return logs emitted by this replica (5-char short ID).", + "schema": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Replica" + } + }, + { + "name": "request_id", + "in": "query", + "required": false, + "description": "Only return logs tagged with this inference request ID.", + "schema": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Request Id" + } + }, + { + "name": "component", + "in": "query", + "required": false, + "description": "Only return logs from this component.", + "schema": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Component" + } + }, + { + "name": "search_pattern", + "in": "query", + "required": false, + "description": "RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", + "schema": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Search Pattern" + } + }, + { + "name": "includes", + "in": "query", + "required": false, + "description": "Case-sensitive substrings that must all appear in the log message.", + "schema": { + "items": { + "type": "string" + }, + "maxItems": 8, + "title": "Includes", + "type": "array" + } + }, + { + "name": "excludes", + "in": "query", + "required": false, + "description": "Case-sensitive substrings; lines containing any of these are dropped.", + "schema": { + "items": { + "type": "string" + }, + "maxItems": 8, + "title": "Excludes", + "type": "array" + } } ], - "description": "Immediately completes the rolling promotion, shifting all traffic to the new version. This works even if the promotion is in the process of rolling back.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SignalPromotionResponseV1" + "$ref": "#/components/schemas/GetLogsResponseV1" } } } @@ -1997,242 +1935,209 @@ "$ref": "#/components/parameters/model_id" }, { - "$ref": "#/components/parameters/env_name" + "$ref": "#/components/parameters/deployment_id" } - ] - }, - "/v1/chains": { - "get": { - "summary": "Gets all chains", + ], + "post": { + "summary": "Gets the logs for a model deployment (deprecated; use GET)", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"start_epoch_millis\": null,\n \"end_epoch_millis\": null,\n \"direction\": null,\n \"limit\": null,\n \"min_level\": null,\n \"replica\": null,\n \"request_id\": null,\n \"component\": null,\n \"search_pattern\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" } ], + "description": "Use the GET form on this path instead.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetDeploymentLogsRequestV1" + } + } + }, + "required": true + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChainsV1" + "$ref": "#/components/schemas/GetLogsResponseV1" } } } } - } + }, + "x-stability": "deprecated", + "deprecated": true } }, - "/v1/chains/{chain_id}": { - "delete": { - "summary": "Deletes a chain by ID", + "/v1/models/{model_id}/deployments/{deployment_id}/patches": { + "post": { + "summary": "Stages a patch against a development deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/chains/{chain_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"prev_patch_hash\": null,\n \"next_patch_point\": {\n \"content_hashes\": null,\n \"config\": null\n },\n \"patch_ops\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'prev_patch_hash': None, 'next_patch_point': {'content_hashes': None, 'config': None}, 'patch_ops': None}\n)\n\nprint(response.text)" } ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChainTombstoneV1" - } + "description": "Persists a patch durably without applying it; call the sync endpoint to apply staged patches to the running deployment. The target must be a development deployment (its archive created with `is_development` set to `true`); patching any other deployment is rejected.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateDeploymentPatchRequestV1" } } - } - } - }, - "parameters": [ - { - "$ref": "#/components/parameters/chain_id" - } - ], - "get": { - "summary": "Gets a chain by ID", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" }, - { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } - ], + "required": true + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChainV1" + "$ref": "#/components/schemas/CreateDeploymentPatchResponseV1" } } } } + }, + "x-stability": "unstable" + }, + "parameters": [ + { + "$ref": "#/components/parameters/model_id" + }, + { + "$ref": "#/components/parameters/deployment_id" } - } + ] }, - "/v1/chains/{chain_id}/deployments": { + "/v1/models/{model_id}/deployments/{deployment_id}/patches/state": { "get": { - "summary": "Gets all chain deployments", + "summary": "Gets a development deployment's patch state", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/state \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/state\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], + "description": "Returns the patch point the deployment is recorded as running and the latest staged-but-unsynced point, if any. The watch client computes its next patch off the pending point when present, else the running point.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChainDeploymentsV1" + "$ref": "#/components/schemas/GetDeploymentPatchesStateResponseV1" } } } } - } + }, + "x-stability": "unstable" }, "parameters": [ { - "$ref": "#/components/parameters/chain_id" + "$ref": "#/components/parameters/model_id" + }, + { + "$ref": "#/components/parameters/deployment_id" } ] }, - "/v1/chains/{chain_id}/deployments/{chain_deployment_id}": { - "delete": { - "summary": "Deletes a chain deployment by ID", + "/v1/models/{model_id}/deployments/{deployment_id}/patches/sync": { + "post": { + "summary": "Syncs staged patches to a development deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/sync \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/sync\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], + "description": "Applies any staged patches to the running deployment. A 2xx response means the sync reached a verdict: in sync, or a full push is required (needs_full_deploy_reason). A 503 means the sync was not attempted or failed recoverably and should be retried; any other error is terminal.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SyncDeploymentPatchesRequestV1" + } + } + }, + "required": true + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChainDeploymentTombstoneV1" + "$ref": "#/components/schemas/SyncDeploymentPatchesResponseV1" } } } } - } + }, + "x-stability": "unstable" }, "parameters": [ { - "$ref": "#/components/parameters/chain_id" + "$ref": "#/components/parameters/model_id" }, { - "$ref": "#/components/parameters/chain_deployment_id" + "$ref": "#/components/parameters/deployment_id" } - ], + ] + }, + "/v1/models/{model_id}/deployments/{deployment_id}/metrics": { "get": { - "summary": "Gets a chain deployment by ID", + "summary": "Gets the metrics for a model deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChainDeploymentV1" - } - } - } - } - } - } - }, - "/v1/chains/{chain_id}/deployments/{chain_deployment_id}/deactivate": { - "post": { - "summary": "Deactivates a chain deployment", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/deactivate \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" - }, + "description": "Gets the metrics for a model deployment in the given time range.", + "parameters": [ { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } - ], - "description": "Deactivates a chain deployment and returns the deactivation status.", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeactivateResponseV1" - } - } + "name": "mode", + "in": "query", + "required": false, + "description": "'CURRENT': a single instantaneous snapshot at now; start/end must be omitted. 'SUMMARY': a single value set aggregating the whole window. 'SERIES': evenly-spaced value sets across the window, with the step derived from the window duration.", + "schema": { + "$ref": "#/components/schemas/ModelMetricModeV1", + "default": "CURRENT" } - } - } - }, - "parameters": [ - { - "$ref": "#/components/parameters/chain_id" - }, - { - "$ref": "#/components/parameters/chain_deployment_id" - } - ] - }, - "/v1/chains/{chain_id}/deployments/{chain_deployment_id}/chainlets/{chainlet_id}/logs": { - "get": { - "summary": "Gets the logs for a chainlet within a chain deployment.", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/chainlets/{chainlet_id}/logs \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" }, - { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/chainlets/{chainlet_id}/logs\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } - ], - "description": "Resolves the chainlet (by ID, scoped to the given chain deployment) to its underlying model deployment and returns its logs in the given time range.", - "parameters": [ { "name": "start_epoch_millis", "in": "query", "required": false, - "description": "Epoch millis timestamp to start fetching logs", + "description": "Epoch millis timestamp to start fetching metrics. Defaults to one hour before the end.", "schema": { "anyOf": [ { @@ -2250,7 +2155,7 @@ "name": "end_epoch_millis", "in": "query", "required": false, - "description": "Epoch millis timestamp to end fetching logs", + "description": "Epoch millis timestamp to end fetching metrics. Defaults to the current time. The window between start and end must not exceed 7 days.", "schema": { "anyOf": [ { @@ -2265,40 +2170,16 @@ } }, { - "name": "direction", - "in": "query", - "required": false, - "description": "Sort order for logs", - "schema": { - "anyOf": [ - { - "$ref": "#/components/schemas/SortOrderV1" - }, - { - "type": "null" - } - ], - "default": null - } - }, - { - "name": "limit", + "name": "metrics", "in": "query", "required": false, - "description": "Limit of logs to fetch in a single request", + "description": "Names of the metrics to return; see https://docs.baseten.co/observability/export-metrics/supported-metrics for the available names. When omitted, a default set is returned: baseten_replicas_active, baseten_inference_requests_total, and baseten_end_to_end_response_time_seconds. Unknown names are rejected; valid names that do not apply are omitted from the response.", "schema": { - "anyOf": [ - { - "maximum": 1000, - "minimum": 1, - "type": "integer" - }, - { - "type": "null" - } - ], - "default": 500, - "title": "Limit" + "items": { + "type": "string" + }, + "title": "Metrics", + "type": "array" } } ], @@ -2308,46 +2189,44 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetLogsResponseV1" + "$ref": "#/components/schemas/GetModelMetricsResponseV1" } } } } - } + }, + "x-stability": "unstable" }, "parameters": [ { - "$ref": "#/components/parameters/chain_id" - }, - { - "$ref": "#/components/parameters/chain_deployment_id" + "$ref": "#/components/parameters/model_id" }, { - "$ref": "#/components/parameters/chainlet_id" + "$ref": "#/components/parameters/deployment_id" } ] }, - "/v1/chains/{chain_id}/environments": { - "get": { - "summary": "Get all chain environments", + "/v1/models/{model_id}/deployments/{deployment_id}/replicas/{replica_id}": { + "delete": { + "summary": "Terminates a replica in a deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/replicas/{replica_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/replicas/{replica_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Gets all chain environments for a given chain", + "description": "Terminates a deployment replica and returns the termination status.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EnvironmentsV1" + "$ref": "#/components/schemas/TerminateReplicaResponseV1" } } } @@ -2356,27 +2235,35 @@ }, "parameters": [ { - "$ref": "#/components/parameters/chain_id" + "$ref": "#/components/parameters/model_id" + }, + { + "$ref": "#/components/parameters/deployment_id" + }, + { + "$ref": "#/components/parameters/replica_id" } - ], + ] + }, + "/v1/models/{model_id}/deployments/{deployment_id}/ssh/sign": { "post": { - "summary": "Create a chain environment", + "summary": "Signs an SSH certificate for an inference model", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"staging\",\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n },\n \"chainlet_settings\": [\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 4,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 2,\n \"scale_down_delay\": 63,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"HelloWorld\",\n \"instance_type_id\": \"2x8\"\n },\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": null,\n \"concurrency_target\": null,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 3,\n \"scale_down_delay\": null,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"RandInt\",\n \"instance_type_id\": \"A10Gx8x32\"\n }\n ]\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/ssh/sign \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"public_key\": null,\n \"replica_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'staging', 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': None, 'rolling_deploy_config': None}, 'chainlet_settings': [{'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 4, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 2, 'scale_down_delay': 63, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'HelloWorld', 'instance_type_id': '2x8'}, {'autoscaling_settings': {'autoscaling_window': None, 'concurrency_target': None, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 3, 'scale_down_delay': None, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'RandInt', 'instance_type_id': 'A10Gx8x32'}]}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/ssh/sign\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'public_key': None, 'replica_id': None}\n)\n\nprint(response.text)" } ], - "description": "Create a chain environment. Returns the resulting environment.", + "description": "Signs a short-lived SSH certificate granting access to a running inference model pod. Returns the signed SSH certificate, a JWT token for SSH proxy authentication, the proxy address to connect through, and the certificate expiry time.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateChainEnvironmentRequestV1" + "$ref": "#/components/schemas/SignSSHCertificateRequestV1" } } }, @@ -2388,35 +2275,43 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChainEnvironmentV1" + "$ref": "#/components/schemas/SignSSHCertificateResponseV1" } } } } } - } + }, + "parameters": [ + { + "$ref": "#/components/parameters/model_id" + }, + { + "$ref": "#/components/parameters/deployment_id" + } + ] }, - "/v1/chains/{chain_id}/environments/{env_name}": { + "/v1/models/{model_id}/environments": { "get": { - "summary": "Get a chain environment's details", + "summary": "Gets all environments", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Gets a chain environment's details and returns the chain environment.", + "description": "Gets all environments for a given model.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChainEnvironmentV1" + "$ref": "#/components/schemas/EnvironmentsV1" } } } @@ -2425,30 +2320,27 @@ }, "parameters": [ { - "$ref": "#/components/parameters/chain_id" - }, - { - "$ref": "#/components/parameters/env_name" + "$ref": "#/components/parameters/model_id" } ], - "patch": { - "summary": "Update a chain environment's settings", + "post": { + "summary": "Creates an environment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": null,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n }\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"staging\",\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 3,\n \"max_replica\": 2,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 60,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": true,\n \"rolling_deploy_config\": null\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': None, 'rolling_deploy': None, 'rolling_deploy_config': None}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'staging', 'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 3, 'max_replica': 2, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 60, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': True, 'rolling_deploy_config': None}}\n)\n\nprint(response.text)" } ], - "description": "Update a chain environment's settings and returns the chain environment.", + "description": "Creates an environment for the specified model and returns the environment.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateChainEnvironmentRequestV1" + "$ref": "#/components/schemas/CreateEnvironmentRequestV1" } } }, @@ -2460,7 +2352,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateChainEnvironmentResponseV1" + "$ref": "#/components/schemas/EnvironmentV1" } } } @@ -2468,37 +2360,27 @@ } } }, - "/v1/chains/{chain_id}/environments/{env_name}/promote": { - "post": { - "summary": "Promotes a chain deployment to an environment", + "/v1/models/{model_id}/environments/{env_name}": { + "get": { + "summary": "Gets an environment's details", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/promote \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_deployment\": true,\n \"deployment_id\": null\n}'" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/promote\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_deployment': True, 'deployment_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Promotes an existing chain deployment to an environment and returns the promoted chain deployment.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PromoteToChainEnvironmentRequestV1" - } - } - }, - "required": true - }, + "description": "Gets an environment's details and returns the environment.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChainDeploymentV1" + "$ref": "#/components/schemas/EnvironmentV1" } } } @@ -2507,32 +2389,30 @@ }, "parameters": [ { - "$ref": "#/components/parameters/chain_id" + "$ref": "#/components/parameters/model_id" }, { "$ref": "#/components/parameters/env_name" } - ] - }, - "/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/autoscaling_settings": { + ], "patch": { - "summary": "Update a chainlet environment's autoscaling settings", + "summary": "Updates an environment's settings", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/autoscaling_settings \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"updates\": [\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 4,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 2,\n \"scale_down_delay\": 63,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"HelloWorld\"\n }\n ]\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 3,\n \"max_replica\": 2,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 60,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'updates': [{'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 4, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 2, 'scale_down_delay': 63, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'HelloWorld'}]}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 3, 'max_replica': 2, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 60, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': None, 'rolling_deploy_config': None}}\n)\n\nprint(response.text)" } ], - "description": "Updates a chainlet environment's autoscaling settings and returns the updated chainlet environment settings.", + "description": "Asynchronously updates an environment's settings. Poll the GET endpoint for the applied state.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateChainletEnvironmentAutoscalingSettingsRequestV1" + "$ref": "#/components/schemas/UpdateEnvironmentRequestV1" } } }, @@ -2550,93 +2430,225 @@ } } } - }, - "parameters": [ - { - "$ref": "#/components/parameters/chain_id" - }, - { - "$ref": "#/components/parameters/env_name" - } - ] + } }, - "/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/instance_types/update": { - "post": { - "summary": "Update a chainlet environment's instance type settings.", + "/v1/models/{model_id}/environments/{env_name}/logs": { + "get": { + "summary": "Gets the logs for a model environment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/instance_types/update \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"updates\": [\n {\n \"chainlet_name\": \"HelloWorld\",\n \"instance_type_id\": \"1x4\"\n },\n {\n \"chainlet_name\": \"RandInt\",\n \"instance_type_id\": \"A10G:2x24x96\"\n }\n ]\n}'" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/instance_types/update\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'updates': [{'chainlet_name': 'HelloWorld', 'instance_type_id': '1x4'}, {'chainlet_name': 'RandInt', 'instance_type_id': 'A10G:2x24x96'}]}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Updates a chainlet environment's instance type settings. The chainlet environment setting must exist. When updated, a new chain deployment is created and deployed. It is promoted to the chain environment according to promotion settings on the environment.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateChainletEnvironmentInstanceTypeRequestV1" - } + "description": "Gets logs across all deployments that were active on the environment in the given time range, which defaults to the last 30 minutes. Pass `start_epoch_millis` to widen the window back to an earlier deployment's build/deploy time.", + "parameters": [ + { + "name": "start_epoch_millis", + "in": "query", + "required": false, + "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Start Epoch Millis" } }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateChainletEnvironmentInstanceTypeResponseV1" + { + "name": "end_epoch_millis", + "in": "query", + "required": false, + "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" } - } + ], + "default": null, + "title": "End Epoch Millis" } - } - } - }, - "parameters": [ - { - "$ref": "#/components/parameters/chain_id" - }, - { - "$ref": "#/components/parameters/env_name" - } - ] - }, - "/v1/teams/{team_id}/training_projects": { - "post": { - "summary": "Upsert a training project in a specific team.", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/training_projects \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"training_project\": {\n \"name\": \"My Training Project\"\n }\n}'" }, { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/training_projects\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_project': {'name': 'My Training Project'}}\n)\n\nprint(response.text)" - } - ], - "description": "Upserts a training project with the specified metadata for a team.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpsertTrainingProjectRequestV1" - } + "name": "direction", + "in": "query", + "required": false, + "description": "Sort order for logs", + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/SortOrderV1" + }, + { + "type": "null" + } + ], + "default": null } }, - "required": true - }, + { + "name": "limit", + "in": "query", + "required": false, + "description": "Limit of logs to fetch in a single request", + "schema": { + "anyOf": [ + { + "maximum": 1000, + "minimum": 1, + "type": "integer" + }, + { + "type": "null" + } + ], + "default": 500, + "title": "Limit" + } + }, + { + "name": "min_level", + "in": "query", + "required": false, + "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level.", + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/LogLevelV1" + }, + { + "type": "null" + } + ], + "default": null + } + }, + { + "name": "replica", + "in": "query", + "required": false, + "description": "Only return logs emitted by this replica (5-char short ID).", + "schema": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Replica" + } + }, + { + "name": "request_id", + "in": "query", + "required": false, + "description": "Only return logs tagged with this inference request ID.", + "schema": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Request Id" + } + }, + { + "name": "component", + "in": "query", + "required": false, + "description": "Only return logs from this component.", + "schema": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Component" + } + }, + { + "name": "search_pattern", + "in": "query", + "required": false, + "description": "RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", + "schema": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Search Pattern" + } + }, + { + "name": "includes", + "in": "query", + "required": false, + "description": "Case-sensitive substrings that must all appear in the log message.", + "schema": { + "items": { + "type": "string" + }, + "maxItems": 8, + "title": "Includes", + "type": "array" + } + }, + { + "name": "excludes", + "in": "query", + "required": false, + "description": "Case-sensitive substrings; lines containing any of these are dropped.", + "schema": { + "items": { + "type": "string" + }, + "maxItems": 8, + "title": "Excludes", + "type": "array" + } + } + ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpsertTrainingProjectResponseV1" + "$ref": "#/components/schemas/GetLogsResponseV1" } } } @@ -2645,95 +2657,168 @@ }, "parameters": [ { - "$ref": "#/components/parameters/team_id" + "$ref": "#/components/parameters/model_id" + }, + { + "$ref": "#/components/parameters/env_name" } ] }, - "/v1/training_projects": { + "/v1/models/{model_id}/environments/{env_name}/metrics": { "get": { - "summary": "List training projects.", + "summary": "Gets the metrics for a model environment.", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Gets metrics aggregated across every deployment that was active on the environment in the given time range. In series mode the window is split at each promotion so that every point reflects the deployment(s) serving the environment at that time.", + "parameters": [ + { + "name": "mode", + "in": "query", + "required": false, + "description": "'CURRENT': a single instantaneous snapshot at now; start/end must be omitted. 'SUMMARY': a single value set aggregating the whole window. 'SERIES': evenly-spaced value sets across the window, with the step derived from the window duration.", + "schema": { + "$ref": "#/components/schemas/ModelMetricModeV1", + "default": "CURRENT" + } + }, + { + "name": "start_epoch_millis", + "in": "query", + "required": false, + "description": "Epoch millis timestamp to start fetching metrics. Defaults to one hour before the end.", + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Start Epoch Millis" + } + }, + { + "name": "end_epoch_millis", + "in": "query", + "required": false, + "description": "Epoch millis timestamp to end fetching metrics. Defaults to the current time. The window between start and end must not exceed 7 days.", + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "End Epoch Millis" + } + }, + { + "name": "metrics", + "in": "query", + "required": false, + "description": "Names of the metrics to return; see https://docs.baseten.co/observability/export-metrics/supported-metrics for the available names. When omitted, a default set is returned: baseten_replicas_active, baseten_inference_requests_total, and baseten_end_to_end_response_time_seconds. Unknown names are rejected; valid names that do not apply are omitted from the response.", + "schema": { + "items": { + "type": "string" + }, + "title": "Metrics", + "type": "array" + } } ], - "description": "List all training projects for the organization.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListTrainingProjectsResponseV1" + "$ref": "#/components/schemas/GetModelMetricsResponseV1" } } } } - } + }, + "x-stability": "unstable" }, + "parameters": [ + { + "$ref": "#/components/parameters/model_id" + }, + { + "$ref": "#/components/parameters/env_name" + } + ] + }, + "/v1/models/{model_id}/environments/{env_name}/activate": { "post": { - "summary": "Upsert a training project.", + "summary": "Activates a deployment associated with an environment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"training_project\": {\n \"name\": \"My Training Project\"\n }\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_project': {'name': 'My Training Project'}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Upserts a training project with the specified metadata.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpsertTrainingProjectRequestV1" - } - } - }, - "required": true - }, + "description": "Activates an inactive deployment associated with an environment and returns the activation status.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpsertTrainingProjectResponseV1" + "$ref": "#/components/schemas/ActivateResponseV1" } } } } } - } + }, + "parameters": [ + { + "$ref": "#/components/parameters/model_id" + }, + { + "$ref": "#/components/parameters/env_name" + } + ] }, - "/v1/training_projects/{training_project_id}/jobs": { - "get": { - "summary": "List training jobs.", + "/v1/models/{model_id}/environments/{env_name}/deactivate": { + "post": { + "summary": "Deactivates a deployment associated with an environment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "List all training jobs for the training project.", + "description": "Deactivates a deployment associated with an environment and returns the deactivation status.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListTrainingJobsResponseV1" + "$ref": "#/components/schemas/DeactivateResponseV1" } } } @@ -2742,27 +2827,32 @@ }, "parameters": [ { - "$ref": "#/components/parameters/training_project_id" + "$ref": "#/components/parameters/model_id" + }, + { + "$ref": "#/components/parameters/env_name" } - ], + ] + }, + "/v1/models/{model_id}/environments/{env_name}/promote": { "post": { - "summary": "Create a training job.", + "summary": "Promotes a deployment to an environment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"training_job\": {\n \"image\": {\n \"base_image\": \"hello-world\",\n \"docker_auth\": null\n },\n \"compute\": {\n \"node_count\": 1,\n \"cpu_count\": 1,\n \"memory\": \"2Gi\",\n \"accelerator\": {\n \"accelerator\": \"H100\",\n \"count\": 2\n }\n },\n \"runtime\": {\n \"start_commands\": [\n \"python main.py\"\n ],\n \"environment_variables\": {\n \"API_KEY\": \"your_api_key_here\",\n \"PATH\": \"/usr/bin\"\n },\n \"artifacts\": null,\n \"enable_cache\": true,\n \"cache_config\": {\n \"enable_legacy_hf_mount\": true,\n \"enabled\": true,\n \"mount_base_path\": \"/root/.cache\",\n \"require_cache_affinity\": true\n },\n \"checkpointing_config\": {\n \"enabled\": true,\n \"checkpoint_path\": \"/mnt/ckpts\",\n \"volume_size_gib\": 10\n },\n \"load_checkpoint_config\": null\n },\n \"name\": \"gpt-oss-job\",\n \"truss_user_env\": null,\n \"interactive_session\": null,\n \"weights\": [\n {\n \"allow_patterns\": null,\n \"auth\": null,\n \"auth_secret_name\": null,\n \"ignore_patterns\": null,\n \"mount_location\": \"/app/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B@main\"\n }\n ],\n \"enable_baseten_workdir\": false,\n \"priority\": 0\n }\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_deployment\": true,\n \"deployment_id\": null,\n \"preserve_env_instance_type\": true\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_job': {'image': {'base_image': 'hello-world', 'docker_auth': None}, 'compute': {'node_count': 1, 'cpu_count': 1, 'memory': '2Gi', 'accelerator': {'accelerator': 'H100', 'count': 2}}, 'runtime': {'start_commands': ['python main.py'], 'environment_variables': {'API_KEY': 'your_api_key_here', 'PATH': '/usr/bin'}, 'artifacts': None, 'enable_cache': True, 'cache_config': {'enable_legacy_hf_mount': True, 'enabled': True, 'mount_base_path': '/root/.cache', 'require_cache_affinity': True}, 'checkpointing_config': {'enabled': True, 'checkpoint_path': '/mnt/ckpts', 'volume_size_gib': 10}, 'load_checkpoint_config': None}, 'name': 'gpt-oss-job', 'truss_user_env': None, 'interactive_session': None, 'weights': [{'allow_patterns': None, 'auth': None, 'auth_secret_name': None, 'ignore_patterns': None, 'mount_location': '/app/models/base', 'source': 'hf://meta-llama/Llama-3-8B@main'}], 'enable_baseten_workdir': False, 'priority': 0}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_deployment': True, 'deployment_id': None, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" } ], - "description": "Creates a training job with the specified configuration.", + "description": "Promotes an existing deployment to an environment and returns the promoted deployment.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateTrainingJobRequestV1" + "$ref": "#/components/schemas/PromoteToEnvironmentRequestV1" } } }, @@ -2774,35 +2864,43 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateTrainingJobResponseV1" + "$ref": "#/components/schemas/DeploymentV1" } } } } } - } + }, + "parameters": [ + { + "$ref": "#/components/parameters/model_id" + }, + { + "$ref": "#/components/parameters/env_name" + } + ] }, - "/v1/training_projects/{training_project_id}/jobs/{training_job_id}": { - "delete": { - "summary": "Delete a training job.", + "/v1/models/{model_id}/environments/{env_name}/cancel_promotion": { + "post": { + "summary": "Cancels a promotion to an environment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/cancel_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/cancel_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Deletes a training job. Stops it first if still running.", + "description": "Cancels an ongoing promotion to an environment and returns the cancellation status.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TrainingJobTombstoneV1" + "$ref": "#/components/schemas/CancelPromotionResponseV1" } } } @@ -2811,60 +2909,70 @@ }, "parameters": [ { - "$ref": "#/components/parameters/training_project_id" + "$ref": "#/components/parameters/model_id" }, { - "$ref": "#/components/parameters/training_job_id" + "$ref": "#/components/parameters/env_name" } - ], - "get": { - "summary": "Get a training job.", + ] + }, + "/v1/models/{model_id}/environments/{env_name}/pause_promotion": { + "post": { + "summary": "Pauses a rolling promotion", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/pause_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/pause_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Get the details of an existing training job.", + "description": "Pauses an in-progress rolling promotion after the current step completes. No further scaling changes are made until resumed.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetTrainingJobResponseV1" + "$ref": "#/components/schemas/SignalPromotionResponseV1" } } } } } - } + }, + "parameters": [ + { + "$ref": "#/components/parameters/model_id" + }, + { + "$ref": "#/components/parameters/env_name" + } + ] }, - "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/download": { - "get": { - "summary": "Get the uploaded training job as a S3 Artifact", + "/v1/models/{model_id}/environments/{env_name}/resume_promotion": { + "post": { + "summary": "Resumes a paused rolling promotion", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/download \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/resume_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/download\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/resume_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Get the uploaded training job as a S3 Artifact", + "description": "Resumes a paused rolling promotion, continuing from where it was paused.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DownloadTrainingJobResponseV1" + "$ref": "#/components/schemas/SignalPromotionResponseV1" } } } @@ -2873,34 +2981,34 @@ }, "parameters": [ { - "$ref": "#/components/parameters/training_project_id" + "$ref": "#/components/parameters/model_id" }, { - "$ref": "#/components/parameters/training_job_id" + "$ref": "#/components/parameters/env_name" } ] }, - "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/recreate": { + "/v1/models/{model_id}/environments/{env_name}/force_cancel_promotion": { "post": { - "summary": "Recreate a training job", + "summary": "Force cancels a rolling promotion", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/recreate \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/force_cancel_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/recreate\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/force_cancel_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Create a new training job with the same configuration as an existing training job.", + "description": "Immediately cancels an in-progress rolling promotion and triggers rollback to the previous version.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RecreateTrainingJobResponseV1" + "$ref": "#/components/schemas/SignalPromotionResponseV1" } } } @@ -2909,109 +3017,34 @@ }, "parameters": [ { - "$ref": "#/components/parameters/training_project_id" + "$ref": "#/components/parameters/model_id" }, { - "$ref": "#/components/parameters/training_job_id" + "$ref": "#/components/parameters/env_name" } ] }, - "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs": { - "get": { - "summary": "Get the logs for a training job.", + "/v1/models/{model_id}/environments/{env_name}/force_roll_forward_promotion": { + "post": { + "summary": "Force rolls forward a rolling promotion", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/force_roll_forward_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } - ], - "description": "Get the logs for a training job with the provided filters.", - "parameters": [ - { - "name": "start_epoch_millis", - "in": "query", - "required": false, - "description": "Epoch millis timestamp to start fetching logs", - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Start Epoch Millis" - } - }, - { - "name": "end_epoch_millis", - "in": "query", - "required": false, - "description": "Epoch millis timestamp to end fetching logs", - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "End Epoch Millis" - } - }, - { - "name": "direction", - "in": "query", - "required": false, - "description": "Sort order for logs", - "schema": { - "anyOf": [ - { - "$ref": "#/components/schemas/SortOrderV1" - }, - { - "type": "null" - } - ], - "default": null - } - }, - { - "name": "limit", - "in": "query", - "required": false, - "description": "Limit of logs to fetch in a single request", - "schema": { - "anyOf": [ - { - "maximum": 1000, - "minimum": 1, - "type": "integer" - }, - { - "type": "null" - } - ], - "default": 500, - "title": "Limit" - } + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/force_roll_forward_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], + "description": "Immediately completes the rolling promotion, shifting all traffic to the new version. This works even if the promotion is in the process of rolling back.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetLogsResponseV1" + "$ref": "#/components/schemas/SignalPromotionResponseV1" } } } @@ -3020,101 +3053,51 @@ }, "parameters": [ { - "$ref": "#/components/parameters/training_project_id" + "$ref": "#/components/parameters/model_id" }, { - "$ref": "#/components/parameters/training_job_id" + "$ref": "#/components/parameters/env_name" } - ], - "post": { - "summary": "Get the logs for a training job (deprecated; use GET).", + ] + }, + "/v1/chains": { + "get": { + "summary": "Gets all chains", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"start_epoch_millis\": null,\n \"end_epoch_millis\": null,\n \"direction\": null,\n \"limit\": null\n}'" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Use the GET form on this path instead.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetTrainingJobLogsRequestV1" - } - } - }, - "required": true - }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetLogsResponseV1" + "$ref": "#/components/schemas/ChainsV1" } } } } - }, - "x-stability": "deprecated", - "deprecated": true + } } }, - "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics": { - "get": { - "summary": "Get the metrics for a training job.", + "/v1/chains/{chain_id}": { + "delete": { + "summary": "Deletes a chain by ID", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/chains/{chain_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } - ], - "description": "Get the metrics for a training job.", - "parameters": [ - { - "name": "end_epoch_millis", - "in": "query", - "required": false, - "description": "Epoch millis timestamp to end fetching metrics", - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "End Epoch Millis" - } - }, - { - "name": "start_epoch_millis", - "in": "query", - "required": false, - "description": "Epoch millis timestamp to start fetching metrics.", - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Start Epoch Millis" - } + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -3123,7 +3106,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetTrainingJobMetricsResponseV1" + "$ref": "#/components/schemas/ChainTombstoneV1" } } } @@ -3132,82 +3115,55 @@ }, "parameters": [ { - "$ref": "#/components/parameters/training_project_id" - }, - { - "$ref": "#/components/parameters/training_job_id" + "$ref": "#/components/parameters/chain_id" } ], - "post": { - "summary": "Get the metrics for a training job (deprecated; use GET).", + "get": { + "summary": "Gets a chain by ID", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"end_epoch_millis\": null,\n \"start_epoch_millis\": null\n}'" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'end_epoch_millis': None, 'start_epoch_millis': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Use the GET form on this path instead.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetTrainingJobMetricsRequestV1" - } - } - }, - "required": true - }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetTrainingJobMetricsResponseV1" + "$ref": "#/components/schemas/ChainV1" } } } } - }, - "x-stability": "deprecated", - "deprecated": true + } } }, - "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/stop": { - "post": { - "summary": "Stop a training job.", + "/v1/chains/{chain_id}/deployments": { + "get": { + "summary": "Gets all chain deployments", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/stop \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{}'" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/stop\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Stops a training job.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StopTrainingJobRequestV1" - } - } - }, - "required": true - }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/StopTrainingJobResponseV1" + "$ref": "#/components/schemas/ChainDeploymentsV1" } } } @@ -3216,34 +3172,30 @@ }, "parameters": [ { - "$ref": "#/components/parameters/training_project_id" - }, - { - "$ref": "#/components/parameters/training_job_id" + "$ref": "#/components/parameters/chain_id" } ] }, - "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoints": { - "get": { - "summary": "Get training job checkpoints.", + "/v1/chains/{chain_id}/deployments/{chain_deployment_id}": { + "delete": { + "summary": "Deletes a chain deployment by ID", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoints \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoints\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Get the checkpoints for a training job.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetTrainingJobCheckpointsResponseV1" + "$ref": "#/components/schemas/ChainDeploymentTombstoneV1" } } } @@ -3252,51 +3204,22 @@ }, "parameters": [ { - "$ref": "#/components/parameters/training_project_id" + "$ref": "#/components/parameters/chain_id" }, { - "$ref": "#/components/parameters/training_job_id" + "$ref": "#/components/parameters/chain_deployment_id" } - ] - }, - "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoint_files": { + ], "get": { - "summary": "Get training job checkpoint files.", + "summary": "Gets a chain deployment by ID", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoint_files \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoint_files\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } - ], - "description": "Get presigned URLs for all checkpoint files for a training job.", - "parameters": [ - { - "name": "page_size", - "in": "query", - "required": false, - "description": "Max files per page (default 1000).", - "schema": { - "default": 1000, - "minimum": 1, - "title": "Page Size", - "type": "integer" - } - }, - { - "name": "page_token", - "in": "query", - "required": false, - "description": "Offset into the file list (default 0).", - "schema": { - "default": 0, - "minimum": 0, - "title": "Page Token", - "type": "integer" - } + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -3305,43 +3228,35 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetTrainingJobCheckpointFilesResponseV1" + "$ref": "#/components/schemas/ChainDeploymentV1" } } } } } - }, - "parameters": [ - { - "$ref": "#/components/parameters/training_project_id" - }, - { - "$ref": "#/components/parameters/training_job_id" - } - ] + } }, - "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/auth_codes": { - "get": { - "summary": "Get auth codes for a training job.", + "/v1/chains/{chain_id}/deployments/{chain_deployment_id}/deactivate": { + "post": { + "summary": "Deactivates a chain deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/auth_codes \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/auth_codes\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Get authentication codes for all nodes of a training job's interactive sessions.", + "description": "Deactivates a chain deployment and returns the deactivation status.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetAuthCodesResponseV1" + "$ref": "#/components/schemas/DeactivateResponseV1" } } } @@ -3350,162 +3265,230 @@ }, "parameters": [ { - "$ref": "#/components/parameters/training_project_id" + "$ref": "#/components/parameters/chain_id" }, { - "$ref": "#/components/parameters/training_job_id" + "$ref": "#/components/parameters/chain_deployment_id" } ] }, - "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/interactive_sessions/{session_id}": { - "patch": { - "summary": "Patch an interactive session.", + "/v1/chains/{chain_id}/deployments/{chain_deployment_id}/chainlets/{chainlet_id}/logs": { + "get": { + "summary": "Gets the logs for a chainlet within a chain deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/interactive_sessions/{session_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"timeout_minutes\": null,\n \"trigger\": null\n}'" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/chainlets/{chainlet_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/interactive_sessions/{session_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'timeout_minutes': None, 'trigger': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/chainlets/{chainlet_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Update specific fields on a training job's interactive session. Only provided (non-null) fields are updated.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PatchInteractiveSessionRequestV1" - } + "description": "Resolves the chainlet (by ID, scoped to the given chain deployment) to its underlying model deployment and returns its logs in the given time range.", + "parameters": [ + { + "name": "start_epoch_millis", + "in": "query", + "required": false, + "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Start Epoch Millis" } }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PatchInteractiveSessionResponseV1" + { + "name": "end_epoch_millis", + "in": "query", + "required": false, + "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" } - } + ], + "default": null, + "title": "End Epoch Millis" } - } - } - }, - "parameters": [ - { - "$ref": "#/components/parameters/training_project_id" - }, - { - "$ref": "#/components/parameters/training_job_id" - }, - { - "$ref": "#/components/parameters/session_id" - } - ] - }, - "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/ssh/sign": { - "post": { - "summary": "Sign an SSH certificate for a training job.", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/ssh/sign \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"public_key\": null,\n \"replica_id\": null\n}'" }, { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/ssh/sign\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'public_key': None, 'replica_id': None}\n)\n\nprint(response.text)" - } - ], - "description": "Signs a short-lived SSH certificate granting access to a specific training job pod. Returns the signed SSH certificate, a JWT token for SSH proxy authentication, the proxy address to connect through, and the certificate expiry time.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SignSSHCertificateRequestV1" - } + "name": "direction", + "in": "query", + "required": false, + "description": "Sort order for logs", + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/SortOrderV1" + }, + { + "type": "null" + } + ], + "default": null } }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SignSSHCertificateResponseV1" + { + "name": "limit", + "in": "query", + "required": false, + "description": "Limit of logs to fetch in a single request", + "schema": { + "anyOf": [ + { + "maximum": 1000, + "minimum": 1, + "type": "integer" + }, + { + "type": "null" } - } + ], + "default": 500, + "title": "Limit" } - } - } - }, - "parameters": [ - { - "$ref": "#/components/parameters/training_project_id" - }, - { - "$ref": "#/components/parameters/training_job_id" - } - ] - }, - "/v1/training_projects/{training_project_id}/cache/summary": { - "get": { - "summary": "Get training project cache summary.", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/cache/summary \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" }, { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/cache/summary\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } - ], - "description": "Get the cache summary for the most recent training job in the project.", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetCacheSummaryResponseV1" + "name": "min_level", + "in": "query", + "required": false, + "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level.", + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/LogLevelV1" + }, + { + "type": "null" } - } + ], + "default": null } - } - } - }, - "parameters": [ - { - "$ref": "#/components/parameters/training_project_id" - } - ] - }, - "/v1/training_projects/{training_project_id}": { - "delete": { - "summary": "Delete a training project.", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" }, { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } + "name": "replica", + "in": "query", + "required": false, + "description": "Only return logs emitted by this replica (5-char short ID).", + "schema": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Replica" + } + }, + { + "name": "request_id", + "in": "query", + "required": false, + "description": "Only return logs tagged with this inference request ID.", + "schema": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Request Id" + } + }, + { + "name": "component", + "in": "query", + "required": false, + "description": "Only return logs from this component.", + "schema": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Component" + } + }, + { + "name": "search_pattern", + "in": "query", + "required": false, + "description": "RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", + "schema": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Search Pattern" + } + }, + { + "name": "includes", + "in": "query", + "required": false, + "description": "Case-sensitive substrings that must all appear in the log message.", + "schema": { + "items": { + "type": "string" + }, + "maxItems": 8, + "title": "Includes", + "type": "array" + } + }, + { + "name": "excludes", + "in": "query", + "required": false, + "description": "Case-sensitive substrings; lines containing any of these are dropped.", + "schema": { + "items": { + "type": "string" + }, + "maxItems": 8, + "title": "Excludes", + "type": "array" + } + } ], - "description": "Deletes a training project and all associated training jobs.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TrainingProjectTombstoneV1" + "$ref": "#/components/schemas/GetLogsResponseV1" } } } @@ -3514,55 +3497,66 @@ }, "parameters": [ { - "$ref": "#/components/parameters/training_project_id" + "$ref": "#/components/parameters/chain_id" + }, + { + "$ref": "#/components/parameters/chain_deployment_id" + }, + { + "$ref": "#/components/parameters/chainlet_id" } - ], + ] + }, + "/v1/chains/{chain_id}/environments": { "get": { - "summary": "Get a training project.", + "summary": "Gets all chain environments", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Get the details of an existing training project.", + "description": "Gets all chain environments for a given chain.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetTrainingProjectResponseV1" + "$ref": "#/components/schemas/EnvironmentsV1" } } } } } - } - }, - "/v1/training_jobs/search": { + }, + "parameters": [ + { + "$ref": "#/components/parameters/chain_id" + } + ], "post": { - "summary": "Search training jobs.", + "summary": "Creates a chain environment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_jobs/search \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"project_id\": \"n4q95w5\",\n \"job_id\": \"p7qr9qv\",\n \"statuses\": [\n \"TRAINING_JOB_RUNNING\",\n \"TRAINING_JOB_COMPLETED\"\n ],\n \"order_by\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"staging\",\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n },\n \"chainlet_settings\": [\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 4,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 2,\n \"scale_down_delay\": 63,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"HelloWorld\",\n \"instance_type_id\": \"2x8\"\n },\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": null,\n \"concurrency_target\": null,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 3,\n \"scale_down_delay\": null,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"RandInt\",\n \"instance_type_id\": \"A10Gx8x32\"\n }\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_jobs/search\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'project_id': 'n4q95w5', 'job_id': 'p7qr9qv', 'statuses': ['TRAINING_JOB_RUNNING', 'TRAINING_JOB_COMPLETED'], 'order_by': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'staging', 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': None, 'rolling_deploy_config': None}, 'chainlet_settings': [{'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 4, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 2, 'scale_down_delay': 63, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'HelloWorld', 'instance_type_id': '2x8'}, {'autoscaling_settings': {'autoscaling_window': None, 'concurrency_target': None, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 3, 'scale_down_delay': None, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'RandInt', 'instance_type_id': 'A10Gx8x32'}]}\n)\n\nprint(response.text)" } ], - "description": "Search training jobs for the organization.", + "description": "Creates a chain environment. Returns the resulting environment.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SearchTrainingJobsRequestV1" + "$ref": "#/components/schemas/CreateChainEnvironmentRequestV1" } } }, @@ -3574,7 +3568,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SearchTrainingJobsResponseV1" + "$ref": "#/components/schemas/ChainEnvironmentV1" } } } @@ -3582,25 +3576,59 @@ } } }, - "/v1/trainers/search": { - "post": { - "summary": "Search trainers.", + "/v1/chains/{chain_id}/environments/{env_name}": { + "get": { + "summary": "Gets a chain environment's details", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Gets a chain environment's details and returns the chain environment.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChainEnvironmentV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/chain_id" + }, + { + "$ref": "#/components/parameters/env_name" + } + ], + "patch": { + "summary": "Updates a chain environment's settings", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/trainers/search \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"trainer_id\": \"k4q95w5\"\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": null,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/trainers/search\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'trainer_id': 'k4q95w5'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': None, 'rolling_deploy': None, 'rolling_deploy_config': None}}\n)\n\nprint(response.text)" } ], - "description": "Search trainers visible to the requesting user.", + "description": "Updates a chain environment's settings and returns the chain environment.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SearchTrainersRequestV1" + "$ref": "#/components/schemas/UpdateChainEnvironmentRequestV1" } } }, @@ -3612,7 +3640,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SearchTrainersResponseV1" + "$ref": "#/components/schemas/UpdateChainEnvironmentResponseV1" } } } @@ -3620,25 +3648,25 @@ } } }, - "/v1/trainers/checkpoints/search": { + "/v1/chains/{chain_id}/environments/{env_name}/promote": { "post": { - "summary": "Look up trainer checkpoint info by bt:// URI.", + "summary": "Promotes a chain deployment to an environment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/trainers/checkpoints/search \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"checkpoint_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\"\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_deployment\": true,\n \"deployment_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/trainers/checkpoints/search\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'checkpoint_path': 'bt://loops:k4q95w5/sampler_weights/step-100'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_deployment': True, 'deployment_id': None}\n)\n\nprint(response.text)" } ], - "description": "Look up the metadata for a trainer checkpoint by its bt://loops:/(weights|sampler_weights)/ URI.", + "description": "Promotes an existing chain deployment to an environment and returns the promoted chain deployment.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CheckpointSearchRequestV1" + "$ref": "#/components/schemas/PromoteToChainEnvironmentRequestV1" } } }, @@ -3650,33 +3678,41 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CheckpointSearchResponseV1" + "$ref": "#/components/schemas/ChainDeploymentV1" } } } } } - } + }, + "parameters": [ + { + "$ref": "#/components/parameters/chain_id" + }, + { + "$ref": "#/components/parameters/env_name" + } + ] }, - "/v1/trainer_sessions": { - "post": { - "summary": "Create a trainer session.", + "/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/autoscaling_settings": { + "patch": { + "summary": "Updates a chainlet environment's autoscaling settings", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/trainer_sessions \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"training_project_id\": null\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"updates\": [\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 4,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 2,\n \"scale_down_delay\": 63,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"HelloWorld\"\n }\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/trainer_sessions\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_project_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'updates': [{'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 4, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 2, 'scale_down_delay': 63, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'HelloWorld'}]}\n)\n\nprint(response.text)" } ], - "description": "Creates a TrainerSession for the given training project.", + "description": "Updates a chainlet environment's autoscaling settings and returns the updated chainlet environment settings.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateTrainerSessionRequestV1" + "$ref": "#/components/schemas/UpdateChainletEnvironmentAutoscalingSettingsRequestV1" } } }, @@ -3688,33 +3724,41 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateTrainerSessionResponseV1" + "$ref": "#/components/schemas/UpdateAutoscalingSettingsResponseV1" } } } } } - } + }, + "parameters": [ + { + "$ref": "#/components/parameters/chain_id" + }, + { + "$ref": "#/components/parameters/env_name" + } + ] }, - "/v1/trainer_sessions/{session_id}/trainers": { + "/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/instance_types/update": { "post": { - "summary": "Create a trainer server.", + "summary": "Updates a chainlet environment's instance type settings", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/trainer_sessions/{session_id}/trainers \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"model\": null,\n \"max_seq_len\": null,\n \"lora_rank\": null,\n \"seed\": null,\n \"scale_down_delay_seconds\": null,\n \"checkpoint_path\": \"bt://loops:k4q95w5/weights/step-100\"\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/instance_types/update \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"updates\": [\n {\n \"chainlet_name\": \"HelloWorld\",\n \"instance_type_id\": \"1x4\"\n },\n {\n \"chainlet_name\": \"RandInt\",\n \"instance_type_id\": \"A10G:2x24x96\"\n }\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/trainer_sessions/{session_id}/trainers\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'model': None, 'max_seq_len': None, 'lora_rank': None, 'seed': None, 'scale_down_delay_seconds': None, 'checkpoint_path': 'bt://loops:k4q95w5/weights/step-100'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/instance_types/update\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'updates': [{'chainlet_name': 'HelloWorld', 'instance_type_id': '1x4'}, {'chainlet_name': 'RandInt', 'instance_type_id': 'A10G:2x24x96'}]}\n)\n\nprint(response.text)" } ], - "description": "Creates a TrainerServer and an associated SamplingServer for the given trainer session.", + "description": "Updates a chainlet environment's instance type settings. The chainlet environment setting must exist. When updated, a new chain deployment is created and deployed. It is promoted to the chain environment according to promotion settings on the environment.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateTrainerServerRequestV1" + "$ref": "#/components/schemas/UpdateChainletEnvironmentInstanceTypeRequestV1" } } }, @@ -3726,7 +3770,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateTrainerServerResponseV1" + "$ref": "#/components/schemas/UpdateChainletEnvironmentInstanceTypeResponseV1" } } } @@ -3735,29 +3779,32 @@ }, "parameters": [ { - "$ref": "#/components/parameters/session_id" + "$ref": "#/components/parameters/chain_id" + }, + { + "$ref": "#/components/parameters/env_name" } ] }, - "/v1/trainer_sessions/{session_id}/samplers": { + "/v1/teams/{team_id}/training_projects": { "post": { - "summary": "Create a sampling server.", + "summary": "Upserts a training project in a specific team", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/trainer_sessions/{session_id}/samplers \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"model\": null,\n \"max_seq_length\": null,\n \"checkpoint_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\"\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/training_projects \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"training_project\": {\n \"name\": \"My Training Project\"\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/trainer_sessions/{session_id}/samplers\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'model': None, 'max_seq_length': None, 'checkpoint_path': 'bt://loops:k4q95w5/sampler_weights/step-100'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/training_projects\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_project': {'name': 'My Training Project'}}\n)\n\nprint(response.text)" } ], - "description": "Creates a standalone SamplingServer (not linked to a TrainerServer).", + "description": "Upserts a training project with the specified metadata for a team.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateSamplingServerRequestV1" + "$ref": "#/components/schemas/UpsertTrainingProjectRequestV1" } } }, @@ -3769,7 +3816,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateSamplingServerResponseV1" + "$ref": "#/components/schemas/UpsertTrainingProjectResponseV1" } } } @@ -3778,132 +3825,124 @@ }, "parameters": [ { - "$ref": "#/components/parameters/session_id" + "$ref": "#/components/parameters/team_id" } ] }, - "/v1/trainer_sessions/{session_id}/trainers/{trainer_id}/checkpoints": { + "/v1/training_projects": { "get": { - "summary": "List trainer server checkpoints.", + "summary": "Lists training projects", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/trainer_sessions/{session_id}/trainers/{trainer_id}/checkpoints \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/trainer_sessions/{session_id}/trainers/{trainer_id}/checkpoints\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "List the checkpoints saved by a trainer server.", + "description": "Lists all training projects for the organization.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetTrainerServerCheckpointsResponseV1" + "$ref": "#/components/schemas/ListTrainingProjectsResponseV1" } } } } } }, - "parameters": [ - { - "$ref": "#/components/parameters/session_id" - }, - { - "$ref": "#/components/parameters/trainer_id" - } - ] - }, - "/v1/trainer_sessions/{session_id}/trainers/{trainer_id}/checkpoints/{checkpoint_id}/files": { - "get": { - "summary": "Get trainer server checkpoint files.", + "post": { + "summary": "Upserts a training project", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/trainer_sessions/{session_id}/trainers/{trainer_id}/checkpoints/{checkpoint_id}/files \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"training_project\": {\n \"name\": \"My Training Project\"\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/trainer_sessions/{session_id}/trainers/{trainer_id}/checkpoints/{checkpoint_id}/files\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_project': {'name': 'My Training Project'}}\n)\n\nprint(response.text)" } ], - "description": "Get presigned URLs for the files under a trainer server checkpoint. Returns a paginated list; deviates from Tinker's single-archive-URL shape because trainer weight sync writes an unzipped folder.", + "description": "Upserts a training project with the specified metadata.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpsertTrainingProjectRequestV1" + } + } + }, + "required": true + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetTrainerServerCheckpointFilesResponseV1" + "$ref": "#/components/schemas/UpsertTrainingProjectResponseV1" } } } } } - }, - "parameters": [ - { - "$ref": "#/components/parameters/session_id" - }, - { - "$ref": "#/components/parameters/trainer_id" - }, - { - "$ref": "#/components/parameters/checkpoint_id" - } - ] + } }, - "/v1/loops/capabilities": { + "/v1/training_projects/{training_project_id}/jobs": { "get": { - "summary": "Get Loops server capabilities.", + "summary": "Lists training jobs", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/capabilities \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/capabilities\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Returns the list of models supported by the Loops server, including each model's maximum context length.", + "description": "Lists all training jobs for the training project.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetLoopsCapabilitiesResponseV1" + "$ref": "#/components/schemas/ListTrainingJobsResponseV1" } } } } } - } - }, - "/v1/loops/sessions": { + }, + "parameters": [ + { + "$ref": "#/components/parameters/training_project_id" + } + ], "post": { - "summary": "Create a Loops session.", + "summary": "Creates a training job", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/sessions \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"training_project_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"training_job\": {\n \"image\": {\n \"base_image\": \"hello-world\",\n \"docker_auth\": null\n },\n \"compute\": {\n \"node_count\": 1,\n \"cpu_count\": 1,\n \"memory\": \"2Gi\",\n \"accelerator\": {\n \"accelerator\": \"H100\",\n \"count\": 2\n },\n \"availability_model\": \"spot\"\n },\n \"runtime\": {\n \"start_commands\": [\n \"python main.py\"\n ],\n \"environment_variables\": {\n \"API_KEY\": \"your_api_key_here\",\n \"PATH\": \"/usr/bin\"\n },\n \"enable_cache\": true,\n \"cache_config\": {\n \"enable_legacy_hf_mount\": true,\n \"enabled\": true,\n \"mount_base_path\": \"/root/.cache\",\n \"require_cache_affinity\": true\n },\n \"checkpointing_config\": {\n \"enabled\": true,\n \"checkpoint_path\": \"/mnt/ckpts\",\n \"volume_size_gib\": 10\n },\n \"load_checkpoint_config\": null\n },\n \"name\": \"gpt-oss-job\",\n \"truss_user_env\": null,\n \"interactive_session\": null,\n \"weights\": [\n {\n \"allow_patterns\": null,\n \"auth\": null,\n \"auth_secret_name\": null,\n \"ignore_patterns\": null,\n \"mount_location\": \"/app/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B@main\"\n }\n ],\n \"enable_baseten_workdir\": false,\n \"priority\": 0\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/sessions\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_project_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_job': {'image': {'base_image': 'hello-world', 'docker_auth': None}, 'compute': {'node_count': 1, 'cpu_count': 1, 'memory': '2Gi', 'accelerator': {'accelerator': 'H100', 'count': 2}, 'availability_model': 'spot'}, 'runtime': {'start_commands': ['python main.py'], 'environment_variables': {'API_KEY': 'your_api_key_here', 'PATH': '/usr/bin'}, 'enable_cache': True, 'cache_config': {'enable_legacy_hf_mount': True, 'enabled': True, 'mount_base_path': '/root/.cache', 'require_cache_affinity': True}, 'checkpointing_config': {'enabled': True, 'checkpoint_path': '/mnt/ckpts', 'volume_size_gib': 10}, 'load_checkpoint_config': None}, 'name': 'gpt-oss-job', 'truss_user_env': None, 'interactive_session': None, 'weights': [{'allow_patterns': None, 'auth': None, 'auth_secret_name': None, 'ignore_patterns': None, 'mount_location': '/app/models/base', 'source': 'hf://meta-llama/Llama-3-8B@main'}], 'enable_baseten_workdir': False, 'priority': 0}}\n)\n\nprint(response.text)" } ], - "description": "Creates a Loops session for the given training project.", + "description": "Creates a training job with the specified configuration.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateLoopsSessionRequestV1" + "$ref": "#/components/schemas/CreateTrainingJobRequestV1" } } }, @@ -3915,7 +3954,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateLoopsSessionResponseV1" + "$ref": "#/components/schemas/CreateTrainingJobResponseV1" } } } @@ -3923,27 +3962,27 @@ } } }, - "/v1/loops/sessions/{session_id}": { - "get": { - "summary": "Get a Loops session.", + "/v1/training_projects/{training_project_id}/jobs/{training_job_id}": { + "delete": { + "summary": "Deletes a training job", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/sessions/{session_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/sessions/{session_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Fetch a Loops session by ID.", + "description": "Deletes a training job. Stops it first if still running.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetLoopsSessionResponseV1" + "$ref": "#/components/schemas/TrainingJobTombstoneV1" } } } @@ -3952,99 +3991,56 @@ }, "parameters": [ { - "$ref": "#/components/parameters/session_id" - } - ] - }, - "/v1/loops/runs": { + "$ref": "#/components/parameters/training_project_id" + }, + { + "$ref": "#/components/parameters/training_job_id" + } + ], "get": { - "summary": "List Loops runs.", + "summary": "Gets a training job", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/runs \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/runs\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } - ], - "description": "List Loops runs visible to the requesting user, optionally filtered by run id and/or base model.", - "parameters": [ - { - "name": "run_id", - "in": "query", - "required": false, - "description": "Filter by run ID.", - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "examples": [ - "k4q95w5" - ], - "title": "Run Id" - } - }, - { - "name": "base_model", - "in": "query", - "required": false, - "description": "Filter runs by base model name.", - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "examples": [ - "Qwen/Qwen3-8B" - ], - "title": "Base Model" - } + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], + "description": "Gets the details of an existing training job.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListLoopsRunsResponseV1" + "$ref": "#/components/schemas/GetTrainingJobResponseV1" } } } } } }, - "post": { - "summary": "Create a Loops run.", + "patch": { + "summary": "Updates a training job", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/runs \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"max_seq_len\": null,\n \"lora_rank\": null,\n \"seed\": null,\n \"scale_down_delay_seconds\": null,\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_session_id\": null\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"priority\": 0\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/runs\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'max_seq_len': None, 'lora_rank': None, 'seed': None, 'scale_down_delay_seconds': None, 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_session_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'priority': 0}\n)\n\nprint(response.text)" } ], - "description": "Creates a Loops run with an associated sampler in the given session.", + "description": "Updates mutable fields on a training job. Currently supports changing the queue priority of a PENDING job; higher priorities are dequeued first.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateLoopsRunRequestV1" + "$ref": "#/components/schemas/UpdateTrainingJobRequestV1" } } }, @@ -4056,7 +4052,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateLoopsRunResponseV1" + "$ref": "#/components/schemas/UpdateTrainingJobResponseV1" } } } @@ -4064,27 +4060,27 @@ } } }, - "/v1/loops/runs/{run_id}": { + "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/download": { "get": { - "summary": "Get a Loops run.", + "summary": "Gets presigned URLs for a training job's artifacts", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/runs/{run_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/download \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/runs/{run_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/download\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Fetch a Loops run by ID.", + "description": "Returns presigned S3 URLs for the artifacts uploaded by a training job.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetLoopsRunResponseV1" + "$ref": "#/components/schemas/DownloadTrainingJobResponseV1" } } } @@ -4093,95 +4089,34 @@ }, "parameters": [ { - "$ref": "#/components/parameters/run_id" + "$ref": "#/components/parameters/training_project_id" + }, + { + "$ref": "#/components/parameters/training_job_id" } ] }, - "/v1/loops/samplers": { - "get": { - "summary": "List Loops samplers.", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/samplers \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" - }, - { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } - ], - "description": "List Loops samplers visible to the requesting user.", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListLoopsSamplersResponseV1" - } - } - } - } - } - }, + "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/recreate": { "post": { - "summary": "Create a Loops sampler.", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/samplers \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"max_seq_length\": null,\n \"model_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\",\n \"reuse_from_session_id\": null\n}'" - }, - { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'max_seq_length': None, 'model_path': 'bt://loops:k4q95w5/sampler_weights/step-100', 'reuse_from_session_id': None}\n)\n\nprint(response.text)" - } - ], - "description": "Creates a standalone Loops sampler not linked to a run.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateLoopsSamplerRequestV1" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateLoopsSamplerResponseV1" - } - } - } - } - } - } - }, - "/v1/loops/samplers/{sampler_id}": { - "get": { - "summary": "Get a Loops sampler.", + "summary": "Recreates a training job", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/samplers/{sampler_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/recreate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/samplers/{sampler_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/recreate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Fetch a Loops sampler by ID.", + "description": "Creates a new training job with the same configuration as an existing training job.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetLoopsSamplerResponseV1" + "$ref": "#/components/schemas/RecreateTrainingJobResponseV1" } } } @@ -4190,86 +4125,116 @@ }, "parameters": [ { - "$ref": "#/components/parameters/sampler_id" + "$ref": "#/components/parameters/training_project_id" + }, + { + "$ref": "#/components/parameters/training_job_id" } ] }, - "/v1/loops/checkpoints": { + "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs": { "get": { - "summary": "List Loops checkpoints.", + "summary": "Gets the logs for a training job", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/checkpoints \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/checkpoints\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "List Loops checkpoints filtered by run id, base model, or bt:// URI. Provide exactly one filter.", + "description": "Gets the logs for a training job with the provided filters.", "parameters": [ { - "name": "run_id", + "name": "start_epoch_millis", "in": "query", "required": false, - "description": "Filter by run ID. Returns all checkpoints saved by the run.", + "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", "schema": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "examples": [ - "k4q95w5" - ], - "title": "Run Id" + "title": "Start Epoch Millis" } }, { - "name": "base_model", + "name": "end_epoch_millis", "in": "query", "required": false, - "description": "Filter by base model. Returns checkpoints across the caller's runs of this base model.", + "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", "schema": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "examples": [ - "Qwen/Qwen3-8B" + "title": "End Epoch Millis" + } + }, + { + "name": "direction", + "in": "query", + "required": false, + "description": "Sort order for logs", + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/SortOrderV1" + }, + { + "type": "null" + } ], - "title": "Base Model" + "default": null } }, { - "name": "checkpoint_path", + "name": "limit", "in": "query", "required": false, - "description": "bt:// URI of a Loops checkpoint. Form: bt://loops:/(weights|sampler_weights)/.", + "description": "Limit of logs to fetch in a single request", "schema": { "anyOf": [ { - "type": "string" + "maximum": 1000, + "minimum": 1, + "type": "integer" }, { "type": "null" } ], - "default": null, - "examples": [ - "bt://loops:k4q95w5/sampler_weights/step-100" + "default": 500, + "title": "Limit" + } + }, + { + "name": "min_level", + "in": "query", + "required": false, + "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level.", + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/LogLevelV1" + }, + { + "type": "null" + } ], - "title": "Checkpoint Path" + "default": null } } ], @@ -4279,33 +4244,39 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListLoopsCheckpointsResponseV1" + "$ref": "#/components/schemas/GetLogsResponseV1" } } } } } - } - }, - "/v1/loops/checkpoints/validate": { + }, + "parameters": [ + { + "$ref": "#/components/parameters/training_project_id" + }, + { + "$ref": "#/components/parameters/training_job_id" + } + ], "post": { - "summary": "Validate a Loops checkpoint bt:// URI.", + "summary": "Gets the logs for a training job (deprecated; use GET)", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/checkpoints/validate \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"checkpoint_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\"\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"start_epoch_millis\": null,\n \"end_epoch_millis\": null,\n \"direction\": null,\n \"limit\": null,\n \"min_level\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/checkpoints/validate\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'checkpoint_path': 'bt://loops:k4q95w5/sampler_weights/step-100'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None}\n)\n\nprint(response.text)" } ], - "description": "Whether the caller can manage and use this checkpoint.", + "description": "Use the GET form on this path instead.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ValidateLoopsCheckpointRequestV1" + "$ref": "#/components/schemas/GetTrainingJobLogsRequestV1" } } }, @@ -4317,129 +4288,177 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ValidateLoopsCheckpointResponseV1" + "$ref": "#/components/schemas/GetLogsResponseV1" } } } } - } + }, + "x-stability": "deprecated", + "deprecated": true } }, - "/v1/loops/checkpoints/{checkpoint_id}/files": { + "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics": { "get": { - "summary": "Get Loops checkpoint files.", + "summary": "Gets the metrics for a training job", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/checkpoints/{checkpoint_id}/files \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/checkpoints/{checkpoint_id}/files\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Get presigned URLs for the files under a Loops checkpoint. Returns a paginated list.", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LoopsCheckpointFilesResponseV1" + "description": "Gets the metrics for a training job.", + "parameters": [ + { + "name": "end_epoch_millis", + "in": "query", + "required": false, + "description": "Epoch millis timestamp to end fetching metrics", + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" } - } + ], + "default": null, + "title": "End Epoch Millis" } - } - } - }, - "parameters": [ - { - "$ref": "#/components/parameters/checkpoint_id" - } - ] - }, - "/v1/loops/deployments": { - "get": { - "summary": "List Loops deployments.", - "x-codeSamples": [ + }, { - "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/deployments \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "name": "start_epoch_millis", + "in": "query", + "required": false, + "description": "Epoch millis timestamp to start fetching metrics.", + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Start Epoch Millis" + } }, { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "name": "step_seconds", + "in": "query", + "required": false, + "description": "Resolution of the returned series, in seconds. When omitted, a step is derived from the time range so large windows return fewer points.", + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Step Seconds" + } } ], - "description": "List the caller's Loops deployments. Returns every deployment regardless of status; clients filter terminal states.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListLoopsDeploymentsResponseV1" + "$ref": "#/components/schemas/GetTrainingJobMetricsResponseV1" } } } } } - } - }, - "/v1/loops/deployments/{deployment_id}/deactivate": { + }, + "parameters": [ + { + "$ref": "#/components/parameters/training_project_id" + }, + { + "$ref": "#/components/parameters/training_job_id" + } + ], "post": { - "summary": "Deactivate a Loops deployment.", + "summary": "Gets the metrics for a training job (deprecated; use GET)", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id}/deactivate \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"end_epoch_millis\": null,\n \"start_epoch_millis\": null,\n \"step_seconds\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'end_epoch_millis': None, 'start_epoch_millis': None, 'step_seconds': None}\n)\n\nprint(response.text)" } ], - "description": "Shut down a Loops deployment by ID. Saved checkpoints remain accessible. Resolving base_model -> deployment_id is the caller's responsibility \u2014 list deployments and pick the active one.", + "description": "Use the GET form on this path instead.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetTrainingJobMetricsRequestV1" + } + } + }, + "required": true + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeactivateLoopsDeploymentResponseV1" + "$ref": "#/components/schemas/GetTrainingJobMetricsResponseV1" } } } } - } - }, - "parameters": [ - { - "$ref": "#/components/parameters/deployment_id" - } - ] + }, + "x-stability": "deprecated", + "deprecated": true + } }, - "/v1/loops/deployments/{deployment_id}": { - "get": { - "summary": "Get a Loops deployment.", + "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/stop": { + "post": { + "summary": "Stops a training job", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/stop \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/stop\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Fetch a Loops deployment by ID, including its latest status.", + "description": "Stops a training job.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StopTrainingJobRequestV1" + } + } + }, + "required": true + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetLoopsDeploymentResponseV1" + "$ref": "#/components/schemas/StopTrainingJobResponseV1" } } } @@ -4448,41 +4467,34 @@ }, "parameters": [ { - "$ref": "#/components/parameters/deployment_id" + "$ref": "#/components/parameters/training_project_id" + }, + { + "$ref": "#/components/parameters/training_job_id" } ] }, - "/v1/loops/deployments/{deployment_id}/metrics": { - "post": { - "summary": "Get metrics for a Loops trainer deployment.", + "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoints": { + "get": { + "summary": "Gets training job checkpoints", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id}/metrics \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"end_epoch_millis\": null,\n \"start_epoch_millis\": null\n}'" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'end_epoch_millis': None, 'start_epoch_millis': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Returns per-node GPU/CPU/memory utilization and Knative queue-proxy request rate / concurrency / latency for the trainer pods. The sampler half of a Loops deployment is an OracleVersion and uses the existing model-metrics endpoint.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetLoopsDeploymentMetricsRequestV1" - } - } - }, - "required": true - }, + "description": "Gets the checkpoints for a training job.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetLoopsDeploymentMetricsResponseV1" + "$ref": "#/components/schemas/GetTrainingJobCheckpointsResponseV1" } } } @@ -4491,96 +4503,50 @@ }, "parameters": [ { - "$ref": "#/components/parameters/deployment_id" + "$ref": "#/components/parameters/training_project_id" + }, + { + "$ref": "#/components/parameters/training_job_id" } ] }, - "/v1/loops/deployments/{deployment_id}/logs": { + "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoint_files": { "get": { - "summary": "Get logs for a Loops trainer deployment.", + "summary": "Gets training job checkpoint files", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id}/logs \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoint_files \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoint_files\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Fetch logs from the trainer pods of a Loops deployment. Visible to any member of the deployment's team.", + "description": "Gets presigned URLs for all checkpoint files for a training job.", "parameters": [ { - "name": "start_epoch_millis", - "in": "query", - "required": false, - "description": "Epoch millis timestamp to start fetching logs", - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Start Epoch Millis" - } - }, - { - "name": "end_epoch_millis", - "in": "query", - "required": false, - "description": "Epoch millis timestamp to end fetching logs", - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "End Epoch Millis" - } - }, - { - "name": "direction", + "name": "page_size", "in": "query", "required": false, - "description": "Sort order for logs", + "description": "Max files per page (default 1000).", "schema": { - "anyOf": [ - { - "$ref": "#/components/schemas/SortOrderV1" - }, - { - "type": "null" - } - ], - "default": null + "default": 1000, + "minimum": 1, + "title": "Page Size", + "type": "integer" } }, { - "name": "limit", + "name": "page_token", "in": "query", "required": false, - "description": "Limit of logs to fetch in a single request", + "description": "Offset into the file list (default 0).", "schema": { - "anyOf": [ - { - "maximum": 1000, - "minimum": 1, - "type": "integer" - }, - { - "type": "null" - } - ], - "default": 500, - "title": "Limit" + "default": 0, + "minimum": 0, + "title": "Page Token", + "type": "integer" } } ], @@ -4590,7 +4556,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetLogsResponseV1" + "$ref": "#/components/schemas/GetTrainingJobCheckpointFilesResponseV1" } } } @@ -4599,123 +4565,165 @@ }, "parameters": [ { - "$ref": "#/components/parameters/deployment_id" + "$ref": "#/components/parameters/training_project_id" + }, + { + "$ref": "#/components/parameters/training_job_id" } ] }, - "/v1/training/capacity": { + "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/auth_codes": { "get": { - "summary": "Get training GPU capacity.", + "summary": "Gets auth codes for a training job", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training/capacity \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/auth_codes \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training/capacity\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/auth_codes\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Returns GPU capacity limits (baseline and peak) and current usage for the organization.", + "description": "Gets authentication codes for all nodes of a training job's interactive sessions.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetTrainingGpuCapacityResponseV1" + "$ref": "#/components/schemas/GetAuthCodesResponseV1" } } } } } - } + }, + "parameters": [ + { + "$ref": "#/components/parameters/training_project_id" + }, + { + "$ref": "#/components/parameters/training_job_id" + } + ] }, - "/v1/blobs/credentials/model": { - "get": { - "summary": "Get blob credentials for models.", + "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/interactive_sessions/{session_id}": { + "patch": { + "summary": "Patches an interactive session", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/blobs/credentials/model \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/interactive_sessions/{session_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"timeout_minutes\": null,\n \"trigger\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/blobs/credentials/model\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/interactive_sessions/{session_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'timeout_minutes': None, 'trigger': None}\n)\n\nprint(response.text)" } ], + "description": "Updates specific fields on a training job's interactive session. Only provided (non-null) fields are updated.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchInteractiveSessionRequestV1" + } + } + }, + "required": true + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetBlobCredentialsResponseV1" + "$ref": "#/components/schemas/PatchInteractiveSessionResponseV1" } } } } } - } + }, + "parameters": [ + { + "$ref": "#/components/parameters/training_project_id" + }, + { + "$ref": "#/components/parameters/training_job_id" + }, + { + "$ref": "#/components/parameters/session_id" + } + ] }, - "/v1/blobs/credentials/train": { - "get": { - "summary": "Get blob credentials for training.", + "/v1/training_projects/{training_project_id}/jobs/{training_job_id}/ssh/sign": { + "post": { + "summary": "Signs an SSH certificate for a training job", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/blobs/credentials/train \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/ssh/sign \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"public_key\": null,\n \"replica_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/blobs/credentials/train\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/ssh/sign\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'public_key': None, 'replica_id': None}\n)\n\nprint(response.text)" } ], + "description": "Signs a short-lived SSH certificate granting access to a specific training job pod. Returns the signed SSH certificate, a JWT token for SSH proxy authentication, the proxy address to connect through, and the certificate expiry time.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignSSHCertificateRequestV1" + } + } + }, + "required": true + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetBlobCredentialsResponseV1" + "$ref": "#/components/schemas/SignSSHCertificateResponseV1" } } } } } - } + }, + "parameters": [ + { + "$ref": "#/components/parameters/training_project_id" + }, + { + "$ref": "#/components/parameters/training_job_id" + } + ] }, - "/v1/teams/{team_id}/api_keys": { - "post": { - "summary": "Creates a team API key", + "/v1/training_projects/{training_project_id}/cache/summary": { + "get": { + "summary": "Gets training project cache summary", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/api_keys \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-api-key\",\n \"type\": \"PERSONAL\"\n}'" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/cache/summary \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-api-key', 'type': 'PERSONAL'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/cache/summary\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Creates a team API key with the provided name and type. The API key is returned in the response.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateAPIKeyRequestV1" - } - } - }, - "required": true - }, + "description": "Gets the cache summary for the most recent training job in the project.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/APIKeyV1" + "$ref": "#/components/schemas/GetCacheSummaryResponseV1" } } } @@ -4724,66 +4732,62 @@ }, "parameters": [ { - "$ref": "#/components/parameters/team_id" + "$ref": "#/components/parameters/training_project_id" } ] }, - "/v1/api_keys": { - "get": { - "summary": "Lists the user's API keys (metadata only, no plain text keys)", + "/v1/training_projects/{training_project_id}": { + "delete": { + "summary": "Deletes a training project", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/api_keys \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/api_keys\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], + "description": "Deletes a training project and all associated training jobs.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/APIKeysV1" + "$ref": "#/components/schemas/TrainingProjectTombstoneV1" } } } } } }, - "post": { - "summary": "Creates an API key", + "parameters": [ + { + "$ref": "#/components/parameters/training_project_id" + } + ], + "get": { + "summary": "Gets a training project", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/api_keys \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-api-key\",\n \"type\": \"PERSONAL\"\n}'" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/api_keys\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-api-key', 'type': 'PERSONAL'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Creates an API key with the provided name and type. The API key is returned in the response.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateAPIKeyRequestV1" - } - } - }, - "required": true - }, + "description": "Gets the details of an existing training project.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/APIKeyV1" + "$ref": "#/components/schemas/GetTrainingProjectResponseV1" } } } @@ -4791,96 +4795,93 @@ } } }, - "/v1/api_keys/{api_key_prefix}": { - "delete": { - "summary": "Deletes an API key by prefix", + "/v1/training_jobs/search": { + "post": { + "summary": "Searches training jobs", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/api_keys/{api_key_prefix} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_jobs/search \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"project_id\": \"n4q95w5\",\n \"job_id\": \"p7qr9qv\",\n \"statuses\": [\n \"TRAINING_JOB_RUNNING\",\n \"TRAINING_JOB_COMPLETED\"\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/api_keys/{api_key_prefix}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_jobs/search\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'project_id': 'n4q95w5', 'job_id': 'p7qr9qv', 'statuses': ['TRAINING_JOB_RUNNING', 'TRAINING_JOB_COMPLETED']}\n)\n\nprint(response.text)" } ], - "description": "Deletes an API key by prefix and returns info about the API key.", + "description": "Searches training jobs for the organization.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SearchTrainingJobsRequestV1" + } + } + }, + "required": true + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/APIKeyTombstoneV1" + "$ref": "#/components/schemas/SearchTrainingJobsResponseV1" } } } } } - }, - "parameters": [ - { - "$ref": "#/components/parameters/api_key_prefix" - } - ] + } }, - "/v1/model_apis/snapshots": { + "/v1/loops/capabilities": { "get": { - "summary": "Get the latest model weight snapshot", + "summary": "Gets Loops server capabilities", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/model_apis/snapshots \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/capabilities \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/model_apis/snapshots\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/capabilities\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Gets the most recent model weight snapshot for the specified model.", + "description": "Returns the list of models supported by the Loops server, including each model's maximum context length.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ModelWeightSnapshotV1" + "$ref": "#/components/schemas/GetLoopsCapabilitiesResponseV1" } } } } } - }, + } + }, + "/v1/loops/sessions": { "post": { - "summary": "Create a model weight snapshot", + "summary": "Creates a Loops session", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/model_apis/snapshots \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"model\": null,\n \"snapshot_uri\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/sessions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/model_apis/snapshots\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'model': None, 'snapshot_uri': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/sessions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Creates a model weight snapshot for the specified model and returns the snapshot.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateModelWeightSnapshotRequestV1" - } - } - }, - "required": true - }, + "description": "Creates a Loops session scoped to the calling org.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ModelWeightSnapshotV1" + "$ref": "#/components/schemas/CreateLoopsSessionResponseV1" } } } @@ -4888,27 +4889,27 @@ } } }, - "/v1/model_apis/snapshots/{model_id}": { + "/v1/loops/sessions/{session_id}": { "get": { - "summary": "Get the latest model weight snapshot", + "summary": "Gets a Loops session", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/model_apis/snapshots/{model_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/sessions/{session_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/model_apis/snapshots/{model_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/sessions/{session_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Gets the most recent model weight snapshot for the specified model.", + "description": "Fetches a Loops session by ID.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ModelWeightSnapshotV1" + "$ref": "#/components/schemas/GetLoopsSessionResponseV1" } } } @@ -4917,101 +4918,99 @@ }, "parameters": [ { - "$ref": "#/components/parameters/model_id" + "$ref": "#/components/parameters/session_id" } - ], - "post": { - "summary": "Create a model weight snapshot", + ] + }, + "/v1/loops/runs": { + "get": { + "summary": "Lists Loops runs", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/model_apis/snapshots/{model_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"model\": null,\n \"snapshot_uri\": null\n}'" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/model_apis/snapshots/{model_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'model': None, 'snapshot_uri': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Creates a model weight snapshot for the specified model and returns the snapshot.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateModelWeightSnapshotRequestV1" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ModelWeightSnapshotV1" + "description": "Lists Loops runs visible to the requesting user, optionally filtered by run id and/or base model.", + "parameters": [ + { + "name": "run_id", + "in": "query", + "required": false, + "description": "Filter by run ID.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "default": null, + "examples": [ + "k4q95w5" + ], + "title": "Run Id" } - } - } - } - }, - "/v1/llm_models": { - "post": { - "summary": "Creates a new BIS LLM deployment", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/llm_models \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"llm_version\": null,\n \"llm_config\": null,\n \"environment_variables\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ],\n \"name\": null\n}'" }, { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/llm_models\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'llm_version': None, 'llm_config': None, 'environment_variables': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}], 'name': None}\n)\n\nprint(response.text)" + "name": "base_model", + "in": "query", + "required": false, + "description": "Filter runs by base model name.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "examples": [ + "Qwen/Qwen3-8B" + ], + "title": "Base Model" + } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateLLMModelRequestV1" - } - } - }, - "required": true - }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LLMModelHandleV1" + "$ref": "#/components/schemas/ListLoopsRunsResponseV1" } } } } } - } - }, - "/v1/teams/{team_id}/llm_models": { + }, "post": { - "summary": "Creates a new BIS LLM deployment", + "summary": "Creates a Loops run", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/llm_models \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"llm_version\": null,\n \"llm_config\": null,\n \"environment_variables\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ],\n \"name\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_session_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/llm_models\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'llm_version': None, 'llm_config': None, 'environment_variables': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}], 'name': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_session_id': None}\n)\n\nprint(response.text)" } ], + "description": "Creates a Loops run with an associated sampler in the given session.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateLLMModelRequestV1" + "$ref": "#/components/schemas/CreateLoopsRunRequestV1" } } }, @@ -5023,49 +5022,35 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LLMModelHandleV1" + "$ref": "#/components/schemas/CreateLoopsRunResponseV1" } } } } } - }, - "parameters": [ - { - "$ref": "#/components/parameters/team_id" - } - ] + } }, - "/v1/llm_models/{model_id}/deployments": { - "post": { - "summary": "Creates a new BIS LLM deployment version", + "/v1/loops/runs/{run_id}": { + "get": { + "summary": "Gets a Loops run", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/llm_models/{model_id}/deployments \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"llm_version\": null,\n \"llm_config\": null,\n \"environment_variables\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ]\n}'" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/runs/{run_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/llm_models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'llm_version': None, 'llm_config': None, 'environment_variables': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}]}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/runs/{run_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateLLMModelVersionRequestV1" - } - } - }, - "required": true - }, + "description": "Fetches a Loops run by ID.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LLMModelHandleV1" + "$ref": "#/components/schemas/GetLoopsRunResponseV1" } } } @@ -5074,31 +5059,31 @@ }, "parameters": [ { - "$ref": "#/components/parameters/model_id" + "$ref": "#/components/parameters/run_id" } ] }, - "/v1/library_listings": { + "/v1/loops/samplers": { "get": { - "summary": "Gets all library listings", + "summary": "Lists Loops samplers", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/library_listings \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Returns all library listings for the authenticated user's organization.", + "description": "Lists Loops samplers visible to the requesting user.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LibraryListingsV1" + "$ref": "#/components/schemas/ListLoopsSamplersResponseV1" } } } @@ -5106,23 +5091,23 @@ } }, "post": { - "summary": "Creates a new library listing", + "summary": "Creates a Loops sampler", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/library_listings \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"user_defined_id\": null,\n \"is_public\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"max_seq_length\": null,\n \"model_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\",\n \"reuse_from_session_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'display_name': None, 'user_defined_id': None, 'is_public': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'max_seq_length': None, 'model_path': 'bt://loops:k4q95w5/sampler_weights/step-100', 'reuse_from_session_id': None}\n)\n\nprint(response.text)" } ], - "description": "Creates a new library listing for the authenticated user's organization.", + "description": "Creates a standalone Loops sampler not linked to a run.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateLibraryListingRequestV1" + "$ref": "#/components/schemas/CreateLoopsSamplerRequestV1" } } }, @@ -5134,7 +5119,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LibraryListingV1" + "$ref": "#/components/schemas/CreateLoopsSamplerResponseV1" } } } @@ -5142,27 +5127,27 @@ } } }, - "/v1/library_listings/{user_defined_listing_id}": { - "delete": { - "summary": "Deletes a library listing", + "/v1/loops/samplers/{sampler_id}": { + "get": { + "summary": "Gets a Loops sampler", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/samplers/{sampler_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/samplers/{sampler_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Deletes a library listing and all of its associated versions. Any versions that are currently live will also be removed.", + "description": "Fetches a Loops sampler by ID.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LibraryListingTombstoneV1" + "$ref": "#/components/schemas/GetLoopsSamplerResponseV1" } } } @@ -5171,53 +5156,122 @@ }, "parameters": [ { - "$ref": "#/components/parameters/user_defined_listing_id" + "$ref": "#/components/parameters/sampler_id" } - ], + ] + }, + "/v1/loops/checkpoints": { "get": { - "summary": "Gets a library listing", + "summary": "Lists Loops checkpoints", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/checkpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/checkpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Lists Loops checkpoints filtered by run id, base model, or bt:// URI. Provide exactly one filter.", + "parameters": [ + { + "name": "run_id", + "in": "query", + "required": false, + "description": "Filter by run ID. Returns all checkpoints saved by the run.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "examples": [ + "k4q95w5" + ], + "title": "Run Id" + } + }, + { + "name": "base_model", + "in": "query", + "required": false, + "description": "Filter by base model. Returns checkpoints across the caller's runs of this base model.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "examples": [ + "Qwen/Qwen3-8B" + ], + "title": "Base Model" + } + }, + { + "name": "checkpoint_path", + "in": "query", + "required": false, + "description": "bt:// URI of a Loops checkpoint. Form: bt://loops:/(weights|sampler_weights)/.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "examples": [ + "bt://loops:k4q95w5/sampler_weights/step-100" + ], + "title": "Checkpoint Path" + } } ], - "description": "Returns a specific library listing by its user-defined identifier.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LibraryListingV1" + "$ref": "#/components/schemas/ListLoopsCheckpointsResponseV1" } } } } } - }, - "patch": { - "summary": "Updates a library listing", + } + }, + "/v1/loops/checkpoints/validate": { + "post": { + "summary": "Validates a Loops checkpoint bt:// URI", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"is_public\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/checkpoints/validate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"checkpoint_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'display_name': None, 'is_public': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/checkpoints/validate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'checkpoint_path': 'bt://loops:k4q95w5/sampler_weights/step-100'}\n)\n\nprint(response.text)" } ], - "description": "Updates the display name of a library listing.", + "description": "Returns whether the caller can manage and use this checkpoint.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateLibraryListingRequestV1" + "$ref": "#/components/schemas/ValidateLoopsCheckpointRequestV1" } } }, @@ -5229,7 +5283,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LibraryListingV1" + "$ref": "#/components/schemas/ValidateLoopsCheckpointResponseV1" } } } @@ -5237,27 +5291,27 @@ } } }, - "/v1/library_listings/{user_defined_listing_id}/versions": { + "/v1/loops/checkpoints/{checkpoint_id}/files": { "get": { - "summary": "Gets all versions for a library listing", + "summary": "Gets Loops checkpoint files", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/checkpoints/{checkpoint_id}/files \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/checkpoints/{checkpoint_id}/files\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Returns all versions for a specific library listing.", + "description": "Gets presigned URLs for the files under a Loops checkpoint. Returns a paginated list.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LibraryListingVersionsV1" + "$ref": "#/components/schemas/LoopsCheckpointFilesResponseV1" } } } @@ -5266,39 +5320,31 @@ }, "parameters": [ { - "$ref": "#/components/parameters/user_defined_listing_id" + "$ref": "#/components/parameters/checkpoint_id" } - ], - "post": { - "summary": "Creates a new library listing version", + ] + }, + "/v1/loops/deployments": { + "get": { + "summary": "Lists Loops deployments", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"is_public\": null,\n \"oracle_version_id\": null,\n \"allow_truss_download\": null,\n \"version_tag\": null\n}'" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'display_name': None, 'is_public': None, 'oracle_version_id': None, 'allow_truss_download': None, 'version_tag': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Creates a new library listing version from an existing model version. The model version must be fully built (have an image_uri). If a listing with the given id already exists for the org, a new version is added. Otherwise, a new listing is created.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateLibraryListingVersionRequestV1" - } - } - }, - "required": true - }, + "description": "Lists Loops deployments. Defaults to the caller's own; pass ?scope=org to list every deployment in the caller's organization. Returns every deployment regardless of status; clients filter terminal states.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LibraryListingVersionV1" + "$ref": "#/components/schemas/ListLoopsDeploymentsResponseV1" } } } @@ -5306,27 +5352,27 @@ } } }, - "/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}": { - "delete": { - "summary": "Deletes a library listing version", + "/v1/loops/deployments/{deployment_id}/deactivate": { + "post": { + "summary": "Deactivates a Loops deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Deletes a specific version of a library listing. Deleting a live version will fail with a 400 error \u2014 demote the version first by setting another version as live.", + "description": "Shuts down a Loops deployment by ID. Saved checkpoints remain accessible. Resolving the base model to a deployment ID is the caller's responsibility: list deployments and pick the active one.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LibraryListingVersionTombstoneV1" + "$ref": "#/components/schemas/DeactivateLoopsDeploymentResponseV1" } } } @@ -5335,56 +5381,62 @@ }, "parameters": [ { - "$ref": "#/components/parameters/user_defined_listing_id" - }, - { - "$ref": "#/components/parameters/version_tag" + "$ref": "#/components/parameters/deployment_id" } - ], + ] + }, + "/v1/loops/deployments/{deployment_id}": { "get": { - "summary": "Gets a library listing version", + "summary": "Gets a Loops deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Returns a specific version of a library listing.", + "description": "Fetches a Loops deployment by ID, including its latest status.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LibraryListingVersionV1" + "$ref": "#/components/schemas/GetLoopsDeploymentResponseV1" } } } } } }, - "patch": { - "summary": "Updates a library listing version", + "parameters": [ + { + "$ref": "#/components/parameters/deployment_id" + } + ] + }, + "/v1/loops/deployments/{deployment_id}/metrics": { + "post": { + "summary": "Gets metrics for a Loops trainer deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"is_live\": null,\n \"allow_truss_download\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"end_epoch_millis\": null,\n \"start_epoch_millis\": null,\n \"step_seconds\": null,\n \"time_divisor_seconds\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'is_live': None, 'allow_truss_download': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'end_epoch_millis': None, 'start_epoch_millis': None, 'step_seconds': None, 'time_divisor_seconds': None}\n)\n\nprint(response.text)" } ], - "description": "Updates a library listing version. Setting is_live to true will demote the current live version.", + "description": "Returns per-node GPU/CPU/memory utilization and Knative queue-proxy request rate / concurrency / latency for the trainer pods. The sampler half of a Loops deployment is an OracleVersion and uses the existing model-metrics endpoint.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateLibraryListingVersionRequestV1" + "$ref": "#/components/schemas/GetLoopsDeploymentMetricsRequestV1" } } }, @@ -5396,49 +5448,122 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LibraryListingVersionV1" + "$ref": "#/components/schemas/GetLoopsDeploymentMetricsResponseV1" } } } } } - } + }, + "parameters": [ + { + "$ref": "#/components/parameters/deployment_id" + } + ] }, - "/v1/billing/usage_summary": { + "/v1/loops/deployments/{deployment_id}/logs": { "get": { - "summary": "Gets billing usage summary for a date range", + "summary": "Gets logs for a Loops trainer deployment", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/billing/usage_summary \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/billing/usage_summary\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Returns billing usage data within the specified date range. Includes dedicated model serving, training, and model APIs usage. The date range must not exceed 31 days.", + "description": "Fetches logs from the trainer pods of a Loops deployment. Visible to any member of the deployment's team.", "parameters": [ { - "name": "start_date", + "name": "start_epoch_millis", "in": "query", - "required": true, - "description": "Start date (ISO 8601, UTC). Earliest queryable: 2026-01-01.", + "required": false, + "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", "schema": { - "format": "date-time", - "title": "Start Date", - "type": "string" + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Start Epoch Millis" } }, { - "name": "end_date", + "name": "end_epoch_millis", "in": "query", - "required": true, - "description": "End date in ISO 8601 format (UTC). Date range cannot exceed 31 days.", + "required": false, + "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", "schema": { - "format": "date-time", - "title": "End Date", - "type": "string" + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "End Epoch Millis" + } + }, + { + "name": "direction", + "in": "query", + "required": false, + "description": "Sort order for logs", + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/SortOrderV1" + }, + { + "type": "null" + } + ], + "default": null + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "description": "Limit of logs to fetch in a single request", + "schema": { + "anyOf": [ + { + "maximum": 1000, + "minimum": 1, + "type": "integer" + }, + { + "type": "null" + } + ], + "default": 500, + "title": "Limit" + } + }, + { + "name": "min_level", + "in": "query", + "required": false, + "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level.", + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/LogLevelV1" + }, + { + "type": "null" + } + ], + "default": null } } ], @@ -5448,58 +5573,128 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UsageSummaryV1" + "$ref": "#/components/schemas/GetLogsResponseV1" } } } } } - } + }, + "parameters": [ + { + "$ref": "#/components/parameters/deployment_id" + } + ] }, - "/v1/users/{user_id}": { + "/v1/training/capacity": { "get": { - "summary": "Gets a user by ID", + "summary": "Gets training GPU capacity", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/users/{user_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training/capacity \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/users/{user_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training/capacity\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Returns user info. Currently only 'me' is accepted as user_id.", + "description": "Returns GPU capacity limits (baseline and peak) and current usage for the organization.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UserInfoV1" + "$ref": "#/components/schemas/GetTrainingGpuCapacityResponseV1" + } + } + } + } + } + }, + "patch": { + "summary": "Sets a team's training GPU capacity", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/training/capacity \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"team_id\": null,\n \"gpu_type\": null,\n \"max_gpus\": 8\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training/capacity\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'team_id': None, 'gpu_type': None, 'max_gpus': 8}\n)\n\nprint(response.text)" + } + ], + "description": "Sets the max concurrent GPUs of a given type a team may use. Creates the limit if one doesn't exist for this (team, gpu_type) pair, otherwise updates it in place. Org-admin only: this is a ceiling the org imposes on the team, not something the team manages for itself.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchTeamTrainingGpuCapacityRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchTeamTrainingGpuCapacityResponseV1" } } } } } + } + }, + "/v1/training/jobs/{training_job_id}/queue_context": { + "get": { + "summary": "Reconstructs queue context for a training job", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training/jobs/{training_job_id}/queue_context \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training/jobs/{training_job_id}/queue_context\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Returns the (org, gpu_type) capacity pool the job was gated by, jobs that were holding GPU capacity in that pool when this job was submitted, and every TrainingJobStatus event in [submitted_at, released_at] for those jobs, useful for understanding why a job sat in PENDING. Caller must be an org admin and the job must belong to the caller's org.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetTrainingJobQueueContextResponseV1" + } + } + } + } + }, + "x-stability": "unstable" }, "parameters": [ { - "$ref": "#/components/parameters/user_id" + "$ref": "#/components/parameters/training_job_id" } ] }, - "/v1/gateway/groups": { + "/v1/blobs/credentials/model": { "get": { - "summary": "List groups", + "summary": "Gets blob credentials for models", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/groups \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/blobs/credentials/model \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/blobs/credentials/model\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -5508,31 +5703,60 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GroupsResponseV1" + "$ref": "#/components/schemas/GetBlobCredentialsResponseV1" } } } } } - }, + } + }, + "/v1/blobs/credentials/train": { + "get": { + "summary": "Gets blob credentials for training", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/blobs/credentials/train \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/blobs/credentials/train\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetBlobCredentialsResponseV1" + } + } + } + } + } + } + }, + "/v1/teams/{team_id}/api_keys": { "post": { - "summary": "Create a group", + "summary": "Creates a team API key", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/gateway/groups \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"metadata\": {\n \"name\": \"Acme prod\",\n \"external_entity_id\": \"cust_42\"\n },\n \"models\": null,\n \"hierarchy\": {\n \"limit_enforcement\": \"INDEPENDENT\",\n \"parent_group_id\": \"abc123\"\n }\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-api-key\",\n \"type\": \"PERSONAL\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'metadata': {'name': 'Acme prod', 'external_entity_id': 'cust_42'}, 'models': None, 'hierarchy': {'limit_enforcement': 'INDEPENDENT', 'parent_group_id': 'abc123'}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-api-key', 'type': 'PERSONAL'}\n)\n\nprint(response.text)" } ], - "description": "Creates a group and its endpoint configuration", + "description": "Creates a team API key with the provided name and type. The API key is returned in the response.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateGroupRequestV1" + "$ref": "#/components/schemas/CreateAPIKeyRequestV1" } } }, @@ -5544,63 +5768,64 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GroupV1" + "$ref": "#/components/schemas/APIKeyV1" } } } } } - } + }, + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + } + ] }, - "/v1/gateway/groups/{group_id}": { + "/v1/api_keys": { "get": { - "summary": "Get a group", + "summary": "Lists API keys (metadata only, no plain text keys)", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], + "description": "Returns metadata for your personal API keys and the workspace and team API keys you can manage. Organization admins also receive every member's personal API keys, each with an owner identifying the member it belongs to.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GroupV1" + "$ref": "#/components/schemas/APIKeysV1" } } } } } }, - "parameters": [ - { - "$ref": "#/components/parameters/group_id" - } - ], - "patch": { - "summary": "Update a group", + "post": { + "summary": "Creates an API key", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"metadata\": {\n \"name\": \"Acme Prod\"\n },\n \"models\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-api-key\",\n \"type\": \"PERSONAL\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'metadata': {'name': 'Acme Prod'}, 'models': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-api-key', 'type': 'PERSONAL'}\n)\n\nprint(response.text)" } ], - "description": "Updates the group's mutable fields", + "description": "Creates an API key with the provided name and type. The API key is returned in the response.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateGroupRequestV1" + "$ref": "#/components/schemas/CreateAPIKeyRequestV1" } } }, @@ -5612,7 +5837,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GroupV1" + "$ref": "#/components/schemas/APIKeyV1" } } } @@ -5620,26 +5845,27 @@ } } }, - "/v1/gateway/groups/{group_id}/api_keys": { - "get": { - "summary": "List API keys for a group", + "/v1/api_keys/{api_key_prefix}": { + "delete": { + "summary": "Deletes an API key by prefix", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/api_keys/{api_key_prefix} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/api_keys/{api_key_prefix}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], + "description": "Deletes an API key by prefix and returns info about the API key.", "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/KeysForGroupResponseV1" + "$ref": "#/components/schemas/APIKeyTombstoneV1" } } } @@ -5648,27 +5874,55 @@ }, "parameters": [ { - "$ref": "#/components/parameters/group_id" + "$ref": "#/components/parameters/api_key_prefix" } - ], + ] + }, + "/v1/model_apis/snapshots": { + "get": { + "summary": "Gets the latest model weight snapshot", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/model_apis/snapshots \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/model_apis/snapshots\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Gets the most recent model weight snapshot for the specified model.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModelWeightSnapshotV1" + } + } + } + } + } + }, "post": { - "summary": "Create an API key for a group", + "summary": "Creates a model weight snapshot", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"prod-key-1\"\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/model_apis/snapshots \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"model\": null,\n \"snapshot_uri\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'prod-key-1'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/model_apis/snapshots\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'model': None, 'snapshot_uri': None}\n)\n\nprint(response.text)" } ], - "description": "Creates a new API key for the given group", + "description": "Creates a model weight snapshot for the specified model and returns the snapshot.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateApiKeyForGroupRequestV1" + "$ref": "#/components/schemas/CreateModelWeightSnapshotRequestV1" } } }, @@ -5680,7 +5934,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateApiKeyForGroupResponseV1" + "$ref": "#/components/schemas/ModelWeightSnapshotV1" } } } @@ -5688,25 +5942,56 @@ } } }, - "/v1/gateway/groups/{group_id}/api_keys/register": { + "/v1/model_apis/snapshots/{model_id}": { + "get": { + "summary": "Gets the latest model weight snapshot", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/model_apis/snapshots/{model_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/model_apis/snapshots/{model_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Gets the most recent model weight snapshot for the specified model.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModelWeightSnapshotV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/model_id" + } + ], "post": { - "summary": "Register an API key for a group", + "summary": "Creates a model weight snapshot", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys/register \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-model-api-key\",\n \"key\": \"my-secure-api-key-value\"\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/model_apis/snapshots/{model_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"model\": null,\n \"snapshot_uri\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys/register\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-model-api-key', 'key': 'my-secure-api-key-value'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/model_apis/snapshots/{model_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'model': None, 'snapshot_uri': None}\n)\n\nprint(response.text)" } ], - "description": "Registers a Gateway API key with provided value, name.", + "description": "Creates a model weight snapshot for the specified model and returns the snapshot.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RegisterAPIKeyRequestV1" + "$ref": "#/components/schemas/CreateModelWeightSnapshotRequestV1" } } }, @@ -5718,30 +6003,70 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RegisterAPIKeyResponseV1" + "$ref": "#/components/schemas/ModelWeightSnapshotV1" } } } } } - }, - "parameters": [ - { - "$ref": "#/components/parameters/group_id" - } - ] + } }, - "/v1/gateway/groups/{group_id}/api_keys/{api_key_prefix}": { + "/v1/model_apis": { "get": { - "summary": "Get an API key for a group", + "summary": "Lists Model APIs", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys/{api_key_prefix} \\\n--header \"Authorization: Api-Key $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/model_apis \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys/{api_key_prefix}\"\n\nheaders = {\"Authorization\": f\"Api-Key {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/model_apis\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Lists Model APIs visible to the caller. By default returns the full catalog; pass `added_only=true` to restrict to Model APIs the workspace has added.", + "parameters": [ + { + "name": "cursor", + "in": "query", + "required": false, + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cursor" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "description": "Maximum number of items to return.", + "schema": { + "default": 100, + "maximum": 1000, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "name": "added_only", + "in": "query", + "required": false, + "description": "When true, restrict the result to Model APIs the workspace has added. Defaults to the full visible catalog.", + "schema": { + "default": false, + "title": "Added Only", + "type": "boolean" + } } ], "responses": { @@ -5750,29 +6075,1137 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GatewayKeyInfoV1" + "$ref": "#/components/schemas/ModelAPIsResponseV1" } } } } } - }, - "parameters": [ - { - "$ref": "#/components/parameters/group_id" - }, - { - "$ref": "#/components/parameters/api_key_prefix" - } - ] - } - }, - "openapi": "3.1.0", - "components": { - "schemas": { - "SecretV1": { - "description": "A Baseten secret. Note that we do not support retrieving secret values.", + } + }, + "/v1/model_apis/{model_api_name}": { + "get": { + "summary": "Gets a Model API", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/model_apis/{model_api_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/model_apis/{model_api_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Fetches a Model API by name, with workspace overlay when added.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModelAPIV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/model_api_name" + } + ] + }, + "/v1/llm_models": { + "post": { + "summary": "Creates a new BIS-LLM deployment", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/llm_models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"llm_version\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ],\n \"name\": null\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/llm_models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'llm_version': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}], 'name': None}\n)\n\nprint(response.text)" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateLLMModelRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LLMModelHandleV1" + } + } + } + } + } + } + }, + "/v1/teams/{team_id}/llm_models": { + "post": { + "summary": "Creates a new BIS-LLM deployment", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/llm_models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"llm_version\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ],\n \"name\": null\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/llm_models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'llm_version': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}], 'name': None}\n)\n\nprint(response.text)" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateLLMModelRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LLMModelHandleV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + } + ] + }, + "/v1/llm_models/{model_id}/deployments": { + "post": { + "summary": "Creates a new BIS-LLM deployment version", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/llm_models/{model_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"llm_version\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ]\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/llm_models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'llm_version': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}]}\n)\n\nprint(response.text)" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateLLMModelVersionRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LLMModelHandleV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/model_id" + } + ] + }, + "/v1/library_listings": { + "get": { + "summary": "Gets all library listings", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/library_listings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Returns all library listings for the authenticated user's organization.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LibraryListingsV1" + } + } + } + } + } + }, + "post": { + "summary": "Creates a new library listing", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/library_listings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"user_defined_id\": null\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'display_name': None, 'user_defined_id': None}\n)\n\nprint(response.text)" + } + ], + "description": "Creates a new library listing for the authenticated user's organization.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateLibraryListingRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LibraryListingV1" + } + } + } + } + } + } + }, + "/v1/library_listings/{user_defined_listing_id}": { + "delete": { + "summary": "Deletes a library listing", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Deletes a library listing and all of its associated versions. Any versions that are currently live will also be removed.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LibraryListingTombstoneV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/user_defined_listing_id" + } + ], + "get": { + "summary": "Gets a library listing", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Returns a specific library listing by its user-defined identifier.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LibraryListingV1" + } + } + } + } + } + }, + "patch": { + "summary": "Updates a library listing", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"is_public\": null\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'display_name': None, 'is_public': None}\n)\n\nprint(response.text)" + } + ], + "description": "Updates the display name of a library listing.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateLibraryListingRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LibraryListingV1" + } + } + } + } + } + } + }, + "/v1/library_listings/{user_defined_listing_id}/versions": { + "get": { + "summary": "Gets all versions for a library listing", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Returns all versions for a specific library listing.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LibraryListingVersionsV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/user_defined_listing_id" + } + ], + "post": { + "summary": "Creates a new library listing version", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"oracle_version_id\": null,\n \"version_tag\": null\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'display_name': None, 'oracle_version_id': None, 'version_tag': None}\n)\n\nprint(response.text)" + } + ], + "description": "Creates a new library listing version from an existing model version. The model version must be fully built (have an image_uri). If a listing with the given id already exists for the org, a new version is added. Otherwise, a new listing is created.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateLibraryListingVersionRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LibraryListingVersionV1" + } + } + } + } + } + } + }, + "/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}": { + "delete": { + "summary": "Deletes a library listing version", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Deletes a specific version of a library listing. Deleting a live version will fail with a 400 error; demote the version first by setting another version as live.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LibraryListingVersionTombstoneV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/user_defined_listing_id" + }, + { + "$ref": "#/components/parameters/version_tag" + } + ], + "get": { + "summary": "Gets a library listing version", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Returns a specific version of a library listing.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LibraryListingVersionV1" + } + } + } + } + } + }, + "patch": { + "summary": "Updates a library listing version", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"is_live\": null,\n \"allow_truss_download\": null\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'is_live': None, 'allow_truss_download': None}\n)\n\nprint(response.text)" + } + ], + "description": "Updates a library listing version. Setting is_live to true will demote the current live version.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateLibraryListingVersionRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LibraryListingVersionV1" + } + } + } + } + } + } + }, + "/v1/billing/usage_summary": { + "get": { + "summary": "Gets billing usage summary for a date range", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/billing/usage_summary \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/billing/usage_summary\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Returns billing usage data within the specified date range. Includes dedicated model serving, training, and model APIs usage. The date range must not exceed 31 days.", + "parameters": [ + { + "name": "start_date", + "in": "query", + "required": true, + "description": "Start date (ISO 8601, UTC). Earliest queryable: 2026-01-01.", + "schema": { + "format": "date-time", + "title": "Start Date", + "type": "string" + } + }, + { + "name": "end_date", + "in": "query", + "required": true, + "description": "End date in ISO 8601 format (UTC). Date range cannot exceed 31 days.", + "schema": { + "format": "date-time", + "title": "End Date", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UsageSummaryV1" + } + } + } + } + } + } + }, + "/v1/users": { + "get": { + "summary": "Lists users in the workspace", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/users \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/users\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Returns the workspace's members. Only actual joined members are returned; service accounts, invited users, and pending join requests are excluded.", + "parameters": [ + { + "name": "cursor", + "in": "query", + "required": false, + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cursor" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "description": "Maximum number of items to return.", + "schema": { + "default": 100, + "maximum": 1000, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "name": "email", + "in": "query", + "required": false, + "description": "When set, returns only users with this exact email, if any.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Email" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UsersResponseV1" + } + } + } + } + }, + "x-stability": "unstable" + } + }, + "/v1/users/me": { + "get": { + "summary": "Gets the authenticated user", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/users/me \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/users/me\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Returns info about the user making the request.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserInfoV1" + } + } + } + } + }, + "x-stability": "unstable" + } + }, + "/v1/users/{user_id}": { + "get": { + "summary": "Gets a user by ID", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/users/{user_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/users/{user_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Returns info about a user in the caller's workspace.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserInfoV1" + } + } + } + } + }, + "x-stability": "unstable" + }, + "parameters": [ + { + "$ref": "#/components/parameters/user_id" + } + ] + }, + "/v1/gateway/endpoints": { + "get": { + "summary": "Lists Gateway endpoints", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/endpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/endpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EndpointsResponseV1" + } + } + } + } + } + }, + "post": { + "summary": "Creates a Gateway endpoint", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/gateway/endpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"slug\": \"baseten/mymodel-4\",\n \"targets\": [\n {\n \"environment_name\": \"staging\",\n \"model_id\": \"3kZ9xqd\",\n \"provider\": \"BASETEN\",\n \"target_model\": \"custom/model-name\"\n }\n ]\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/endpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'slug': 'baseten/mymodel-4', 'targets': [{'environment_name': 'staging', 'model_id': '3kZ9xqd', 'provider': 'BASETEN', 'target_model': 'custom/model-name'}]}\n)\n\nprint(response.text)" + } + ], + "description": "Provisions an endpoint for the given slug and its upstream target. Exactly one target is supported at this time. The slug's prefix must be one your organization owns.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateEndpointRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EndpointV1" + } + } + } + } + } + } + }, + "/v1/gateway/endpoints/{endpoint_id}": { + "delete": { + "summary": "Deletes a Gateway endpoint", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/gateway/endpoints/{endpoint_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/endpoints/{endpoint_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EndpointTombstoneV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/endpoint_id" + } + ], + "get": { + "summary": "Gets a Gateway endpoint", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/endpoints/{endpoint_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/endpoints/{endpoint_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EndpointV1" + } + } + } + } + } + }, + "patch": { + "summary": "Updates a Gateway endpoint", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/gateway/endpoints/{endpoint_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"targets\": [\n {\n \"environment_name\": \"staging\",\n \"model_id\": \"3kZ9xqd\",\n \"provider\": \"BASETEN\",\n \"target_model\": \"custom/model-name\"\n }\n ]\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/endpoints/{endpoint_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'targets': [{'environment_name': 'staging', 'model_id': '3kZ9xqd', 'provider': 'BASETEN', 'target_model': 'custom/model-name'}]}\n)\n\nprint(response.text)" + } + ], + "description": "Updates the endpoint's provided mutable fields. If targets are provided, the full target list is replaced. Exactly one target is supported at this time.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateEndpointRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EndpointV1" + } + } + } + } + } + } + }, + "/v1/gateway/groups": { + "get": { + "summary": "Lists groups", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupsResponseV1" + } + } + } + } + } + }, + "post": { + "summary": "Creates a group", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/gateway/groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"metadata\": {\n \"name\": \"Acme prod\",\n \"external_entity_id\": \"cust_42\"\n },\n \"models\": null,\n \"hierarchy\": {\n \"limit_enforcement\": \"INDEPENDENT\",\n \"parent_group_id\": \"abc123\"\n }\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'metadata': {'name': 'Acme prod', 'external_entity_id': 'cust_42'}, 'models': None, 'hierarchy': {'limit_enforcement': 'INDEPENDENT', 'parent_group_id': 'abc123'}}\n)\n\nprint(response.text)" + } + ], + "description": "Creates a group and its endpoint configuration.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateGroupRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupV1" + } + } + } + } + } + } + }, + "/v1/gateway/groups/{group_id}": { + "get": { + "summary": "Gets a group", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/group_id" + } + ], + "patch": { + "summary": "Updates a group", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"metadata\": {\n \"name\": \"Acme Prod\"\n },\n \"models\": null\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'metadata': {'name': 'Acme Prod'}, 'models': None}\n)\n\nprint(response.text)" + } + ], + "description": "Updates the group's mutable fields.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateGroupRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupV1" + } + } + } + } + } + } + }, + "/v1/gateway/groups/{group_id}/api_keys": { + "get": { + "summary": "Lists API keys for a group", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/KeysForGroupResponseV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/group_id" + } + ], + "post": { + "summary": "Creates an API key for a group", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"prod-key-1\"\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'prod-key-1'}\n)\n\nprint(response.text)" + } + ], + "description": "Creates a new API key for the given group.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateApiKeyForGroupRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateApiKeyForGroupResponseV1" + } + } + } + } + } + } + }, + "/v1/gateway/groups/{group_id}/api_keys/register": { + "post": { + "summary": "Registers an API key for a group", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys/register \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-model-api-key\",\n \"key\": \"my-secure-api-key-value\"\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys/register\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-model-api-key', 'key': 'my-secure-api-key-value'}\n)\n\nprint(response.text)" + } + ], + "description": "Registers a Gateway API key with the provided value and name.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegisterAPIKeyRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegisterAPIKeyResponseV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/group_id" + } + ] + }, + "/v1/gateway/groups/{group_id}/api_keys/{api_key_prefix}": { + "get": { + "summary": "Gets an API key for a group", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys/{api_key_prefix} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys/{api_key_prefix}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GatewayKeyInfoV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/group_id" + }, + { + "$ref": "#/components/parameters/api_key_prefix" + } + ] + } + }, + "openapi": "3.1.0", + "components": { + "schemas": { + "SecretV1": { + "description": "A Baseten secret. Note that we do not support retrieving secret values.", "properties": { + "id": { + "description": "Stable identifier for the secret. Unchanged across rotation.", + "examples": [ + "3kZ9xqd" + ], + "title": "Id", + "type": "string" + }, "created_at": { "description": "Time the secret was created in ISO 8601 format", "format": "date-time", @@ -5791,6 +7224,7 @@ } }, "required": [ + "id", "created_at", "name", "team_name" @@ -5857,6 +7291,197 @@ "title": "SecretTombstoneV1", "type": "object" }, + "EnvironmentGroupManageAccessV1": { + "description": "Who is allowed to manage an environment group.", + "properties": { + "is_restricted": { + "description": "Whether the environment is restricted to a specific set of users.", + "title": "Is Restricted", + "type": "boolean" + }, + "users": { + "description": "Users who can manage the environment while it is restricted, including organization and team admins who always have access. Empty when the environment is unrestricted.", + "items": { + "$ref": "#/components/schemas/EnvironmentGroupUserV1" + }, + "title": "Users", + "type": "array" + } + }, + "required": [ + "is_restricted" + ], + "title": "EnvironmentGroupManageAccessV1", + "type": "object" + }, + "EnvironmentGroupUserV1": { + "description": "A user referenced by an environment group's manage access.", + "properties": { + "user_id": { + "description": "Unique identifier for the user.", + "title": "User Id", + "type": "string" + }, + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Email address of the user.", + "title": "Email" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Display name of the user.", + "title": "Name" + } + }, + "required": [ + "user_id" + ], + "title": "EnvironmentGroupUserV1", + "type": "object" + }, + "EnvironmentGroupV1": { + "description": "A team-scoped grouping of same-named environments (e.g. \"production\", \"staging\").\n\nRestricting an environment group limits who can manage the environment of that name\nacross every model and chain in the team.", + "properties": { + "name": { + "description": "Name of the environment group, matching the environment name it governs.", + "examples": [ + "staging" + ], + "title": "Name", + "type": "string" + }, + "team_id": { + "description": "Unique identifier of the team the environment group belongs to.", + "title": "Team Id", + "type": "string" + }, + "team_name": { + "description": "Name of the team the environment group belongs to.", + "title": "Team Name", + "type": "string" + }, + "manage_access": { + "$ref": "#/components/schemas/EnvironmentGroupManageAccessV1", + "description": "Settings controlling who can manage this environment group." + } + }, + "required": [ + "name", + "team_id", + "team_name", + "manage_access" + ], + "title": "EnvironmentGroupV1", + "type": "object" + }, + "PaginationResponseV1": { + "properties": { + "has_more": { + "description": "Whether more items exist after this page.", + "title": "Has More", + "type": "boolean" + }, + "cursor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Opaque cursor to pass into the next request. Null when there is no next page.", + "title": "Cursor" + } + }, + "required": [ + "has_more" + ], + "title": "PaginationResponseV1", + "type": "object" + }, + "EnvironmentGroupsV1": { + "description": "A page of environment groups.", + "properties": { + "items": { + "description": "Items in this page.", + "items": { + "$ref": "#/components/schemas/EnvironmentGroupV1" + }, + "title": "Items", + "type": "array" + }, + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." + } + }, + "required": [ + "items", + "pagination" + ], + "title": "EnvironmentGroupsV1", + "type": "object" + }, + "UpdateEnvironmentGroupManageAccessV1": { + "description": "Manage-access settings to apply to an environment group.", + "properties": { + "is_restricted": { + "description": "Whether to restrict this environment to a specific set of users.", + "title": "Is Restricted", + "type": "boolean" + }, + "user_ids": { + "description": "IDs of users granted manage access while restricted. Only meaningful when is_restricted is true.", + "items": { + "type": "string" + }, + "title": "User Ids", + "type": "array" + } + }, + "required": [ + "is_restricted" + ], + "title": "UpdateEnvironmentGroupManageAccessV1", + "type": "object" + }, + "UpdateEnvironmentGroupRequestV1": { + "description": "A request to update an existing environment group.", + "properties": { + "manage_access": { + "anyOf": [ + { + "$ref": "#/components/schemas/UpdateEnvironmentGroupManageAccessV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Manage-access settings to apply. Omit to leave manage access unchanged." + } + }, + "title": "UpdateEnvironmentGroupRequestV1", + "type": "object" + }, "TeamV1": { "description": "A team.", "properties": { @@ -5903,10 +7528,30 @@ "type": "array" } }, - "required": [ - "teams" - ], - "title": "TeamsV1", + "required": [ + "teams" + ], + "title": "TeamsV1", + "type": "object" + }, + "TeamsRequestV1": { + "description": "Request parameters for listing teams.", + "properties": { + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "When set, returns only the team with this exact name, if any.", + "title": "Name" + } + }, + "title": "TeamsRequestV1", "type": "object" }, "InstanceTypeV1": { @@ -5991,6 +7636,138 @@ "title": "InstanceTypesV1", "type": "object" }, + "LoopsUserConfigV1": { + "description": "The caller's Loops user-level config (accelerator priorities).", + "properties": { + "trainer_accelerator_priority": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Ordered allowlist of GPU types for your Loops trainer deployments, highest priority first. Intersected with the org-level allowlist (org acts as a ceiling). Null means 'inherit the org-level allowlist'.", + "examples": [ + [ + "H100", + "H200" + ] + ], + "title": "Trainer Accelerator Priority" + }, + "sampler_accelerator_priority": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Ordered allowlist of GPU types for your Loops sampler deployments, highest priority first. Intersected with the org-level allowlist (org acts as a ceiling). Null means 'inherit the org-level allowlist'.", + "examples": [ + [ + "H100", + "H200" + ] + ], + "title": "Sampler Accelerator Priority" + } + }, + "required": [ + "trainer_accelerator_priority", + "sampler_accelerator_priority" + ], + "title": "LoopsUserConfigV1", + "type": "object" + }, + "GetLoopsUserConfigResponseV1": { + "description": "Response for ``GET /v1/loops/user_config``.", + "properties": { + "user_config": { + "$ref": "#/components/schemas/LoopsUserConfigV1", + "description": "The caller's Loops user config." + } + }, + "required": [ + "user_config" + ], + "title": "GetLoopsUserConfigResponseV1", + "type": "object" + }, + "PatchLoopsUserConfigRequestV1": { + "description": "Request body for ``PATCH /v1/loops/user_config``.\n\nFollows JSON Merge Patch (RFC 7396) semantics per field: omit the field\nto leave it unchanged, send ``null`` to clear and inherit the org-level\nallowlist, send a list to set the allowlist. Empty lists are rejected\nbecause the storage layer normalizes ``null`` and ``[]`` identically, so\naccepting both would create two ways to spell the same intent.", + "properties": { + "trainer_accelerator_priority": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Ordered list of GPU types for trainer deployments, highest priority first. Send a list to set; send null to clear (inherit org allowlist); omit to leave unchanged. Empty list is rejected.", + "examples": [ + [ + "H100", + "H200" + ] + ], + "title": "Trainer Accelerator Priority" + }, + "sampler_accelerator_priority": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Ordered list of GPU types for sampler deployments, highest priority first. Send a list to set; send null to clear (inherit org allowlist); omit to leave unchanged. Empty list is rejected.", + "examples": [ + [ + "H100", + "H200" + ] + ], + "title": "Sampler Accelerator Priority" + } + }, + "title": "PatchLoopsUserConfigRequestV1", + "type": "object" + }, + "PatchLoopsUserConfigResponseV1": { + "description": "Response for ``PATCH /v1/loops/user_config``.", + "properties": { + "user_config": { + "$ref": "#/components/schemas/LoopsUserConfigV1", + "description": "The updated Loops user config." + } + }, + "required": [ + "user_config" + ], + "title": "PatchLoopsUserConfigResponseV1", + "type": "object" + }, "InstanceTypeWithPriceV1": { "properties": { "instance_type": { @@ -6082,20 +7859,174 @@ "title": "Preserve Env Instance Type", "type": "boolean" }, - "deploy_timeout_minutes": { + "deploy_timeout_minutes": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Deploy timeout in minutes; allowed range 10 to 1440. Server default applies if unset.", + "title": "Deploy Timeout Minutes" + }, + "deployment_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional human-readable name for the deployment.", + "title": "Deployment Name" + }, + "labels": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "User-provided key-value labels for the deployment.", + "title": "Labels" + }, + "is_development": { + "default": false, + "description": "If true, push as a development deployment: the model's single mutable dev slot, created if absent and overwritten in place otherwise. The following fields must be left at their defaults: `environment_name`, `preserve_env_instance_type`, `deployment_name`.", + "title": "Is Development", + "type": "boolean" + } + }, + "required": [ + "config" + ], + "title": "DeploymentArchivePayloadV1", + "type": "object" + }, + "PrepareModelUploadRequestV1": { + "description": "Body for `POST /v1/prepare_model_upload`.\n\nValidates the same payload the commit endpoint will validate, and on\n`dry_run=false` issues STS upload credentials. Exactly one of `name` or\n`model_id` is required: `name` validates the new-model path (`POST\n/v1/models`); `model_id` validates the add-deployment path (`POST\n/v1/models/{model_id}/deployments`).", + "properties": { + "deployment": { + "$ref": "#/components/schemas/DeploymentArchivePayloadV1", + "description": "Deployment-level payload, identical to the payload sent at commit." + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Set to validate a new-model push. Exactly one of `name` or `model_id` is required.", + "title": "Name" + }, + "team_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Team the new model will belong to. Only valid when `name` is set; defaults to the organization's default team when omitted. Must not be set when `model_id` is set (the existing model already has a team).", + "title": "Team Id" + }, + "model_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Set to validate an add-deployment push to an existing model. Exactly one of `name` or `model_id` is required.", + "title": "Model Id" + }, + "dry_run": { + "default": false, + "description": "If true, validate the payload only and do not issue upload credentials. The response sets `creds`, `s3_bucket`, and `s3_key` to `null`.", + "title": "Dry Run", + "type": "boolean" + } + }, + "required": [ + "deployment" + ], + "title": "PrepareModelUploadRequestV1", + "type": "object" + }, + "AWSCredentialsV1": { + "description": "AWS credentials", + "properties": { + "aws_access_key_id": { + "description": "The AWS access key ID", + "title": "Aws Access Key Id", + "type": "string" + }, + "aws_secret_access_key": { + "description": "The AWS secret access key", + "title": "Aws Secret Access Key", + "type": "string" + }, + "aws_session_token": { + "description": "The AWS session token", + "title": "Aws Session Token", + "type": "string" + } + }, + "required": [ + "aws_access_key_id", + "aws_secret_access_key", + "aws_session_token" + ], + "title": "AWSCredentialsV1", + "type": "object" + }, + "PrepareModelUploadResponseV1": { + "description": "Response from `POST /v1/prepare_model_upload`.\n\nOn success with `dry_run=false`, returns STS upload credentials. On success\nwith `dry_run=true`, `creds`, `s3_bucket`, and `s3_key` are `null` and only\nvalidation has run.", + "properties": { + "creds": { + "anyOf": [ + { + "$ref": "#/components/schemas/AWSCredentialsV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "STS credentials to upload the model archive." + }, + "s3_bucket": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Deploy timeout in minutes; allowed range 10 to 1440. Server default applies if unset.", - "title": "Deploy Timeout Minutes" + "description": "S3 bucket the credentials are scoped to.", + "title": "S3 Bucket" }, - "deployment_name": { + "s3_key": { "anyOf": [ { "type": "string" @@ -6105,38 +8036,51 @@ } ], "default": null, - "description": "Optional human-readable name for the deployment.", - "title": "Deployment Name" + "description": "S3 key the credentials are scoped to. Pass this to `POST /v1/models` (in the `model_archive` source) once the upload completes.", + "title": "S3 Key" }, - "labels": { + "s3_region": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "User-provided key-value labels for the deployment.", - "title": "Labels" + "description": "AWS region the S3 bucket resides in.", + "title": "S3 Region" } }, - "required": [ - "config" - ], - "title": "DeploymentArchivePayloadV1", + "title": "PrepareModelUploadResponseV1", "type": "object" }, - "PrepareModelUploadRequestV1": { - "description": "Body for `POST /v1/prepare_model_upload`.\n\nValidates the same payload the commit endpoint will validate, and on\n`dry_run=false` issues STS upload credentials. Exactly one of `name` or\n`model_id` is required: `name` validates the new-model path (`POST\n/v1/models`); `model_id` validates the add-deployment path (`POST\n/v1/models/{model_id}/deployments`).", + "ModelV1": { + "description": "A model.", "properties": { - "deployment": { - "$ref": "#/components/schemas/DeploymentArchivePayloadV1", - "description": "Deployment-level payload, identical to the payload sent at commit." + "id": { + "description": "Unique identifier of the model", + "title": "Id", + "type": "string" + }, + "created_at": { + "description": "Time the model was created in ISO 8601 format", + "format": "date-time", + "title": "Created At", + "type": "string" }, "name": { + "description": "Name of the model", + "title": "Name", + "type": "string" + }, + "deployments_count": { + "description": "Number of deployments of the model", + "title": "Deployments Count", + "type": "integer" + }, + "production_deployment_id": { "anyOf": [ { "type": "string" @@ -6145,11 +8089,10 @@ "type": "null" } ], - "default": null, - "description": "Set to validate a new-model push. Exactly one of `name` or `model_id` is required.", - "title": "Name" + "description": "Unique identifier of the production deployment of the model", + "title": "Production Deployment Id" }, - "team_id": { + "development_deployment_id": { "anyOf": [ { "type": "string" @@ -6158,11 +8101,54 @@ "type": "null" } ], - "default": null, - "description": "Team the new model will belong to. Only valid when `name` is set; defaults to the organization's default team when omitted. Must not be set when `model_id` is set (the existing model already has a team).", - "title": "Team Id" + "description": "Unique identifier of the development deployment of the model", + "title": "Development Deployment Id" }, - "model_id": { + "instance_type_name": { + "description": "Name of the instance type for the production deployment of the model", + "title": "Instance Type Name", + "type": "string" + }, + "team_name": { + "description": "Name of the team associated with the model.", + "title": "Team Name", + "type": "string" + } + }, + "required": [ + "id", + "created_at", + "name", + "deployments_count", + "production_deployment_id", + "development_deployment_id", + "instance_type_name", + "team_name" + ], + "title": "ModelV1", + "type": "object" + }, + "ModelsV1": { + "description": "A list of models.", + "properties": { + "models": { + "items": { + "$ref": "#/components/schemas/ModelV1" + }, + "title": "Models", + "type": "array" + } + }, + "required": [ + "models" + ], + "title": "ModelsV1", + "type": "object" + }, + "ModelsRequestV1": { + "description": "Request parameters for listing models.", + "properties": { + "name": { "anyOf": [ { "type": "string" @@ -6172,150 +8158,288 @@ } ], "default": null, - "description": "Set to validate an add-deployment push to an existing model. Exactly one of `name` or `model_id` is required.", - "title": "Model Id" + "description": "When set, returns only models with this exact name, if any. On a team-scoped route this matches at most one model; on the org-wide route it may match models in multiple teams, since names are unique only within a team.", + "title": "Name" + } + }, + "title": "ModelsRequestV1", + "type": "object" + }, + "LibraryListingSourceV1": { + "description": "Create a model by forking a library listing accessible to the caller's organization.", + "properties": { + "kind": { + "const": "library_listing", + "default": "library_listing", + "title": "Kind", + "type": "string" }, - "dry_run": { - "default": false, - "description": "If true, validate the payload only and do not issue upload credentials. The response sets `creds`, `s3_bucket`, and `s3_key` to `null`.", - "title": "Dry Run", - "type": "boolean" + "lab_display_name": { + "description": "Identifier of the publishing organization, as returned by `GET /v1/library_models`.", + "title": "Lab Display Name", + "type": "string" }, - "is_development": { - "default": false, - "description": "If true, validate a development-deployment push. Only valid when `name` is set. The following `deployment` fields must be left at their defaults: `environment_name`, `preserve_env_instance_type`, `deployment_name`.", - "title": "Is Development", - "type": "boolean" + "user_defined_listing_id": { + "description": "Listing identifier within the publishing organization.", + "title": "User Defined Listing Id", + "type": "string" + }, + "deployed_model_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional name for the new deployed model. Defaults to the listing's configured name.", + "title": "Deployed Model Name" } }, "required": [ - "deployment" + "lab_display_name", + "user_defined_listing_id" ], - "title": "PrepareModelUploadRequestV1", + "title": "LibraryListingSourceV1", "type": "object" }, - "AWSCredentialsV1": { - "description": "AWS credentials", + "ModelArchiveSourceV1": { + "description": "Create a model from an archive previously uploaded via the credentials\nissued by `POST /v1/prepare_model_upload`.", "properties": { - "aws_access_key_id": { - "description": "The AWS access key ID", - "title": "Aws Access Key Id", + "kind": { + "const": "model_archive", + "default": "model_archive", + "title": "Kind", "type": "string" }, - "aws_secret_access_key": { - "description": "The AWS secret access key", - "title": "Aws Secret Access Key", + "name": { + "description": "Name of the new model.", + "title": "Name", "type": "string" }, - "aws_session_token": { - "description": "The AWS session token", - "title": "Aws Session Token", + "deployment": { + "$ref": "#/components/schemas/DeploymentArchivePayloadV1", + "description": "Deployment-level configuration for the model's first deployment." + }, + "s3_key": { + "description": "S3 key of the uploaded archive, from the credentials returned by `POST /v1/prepare_model_upload`.", + "title": "S3 Key", "type": "string" + }, + "disable_archive_download": { + "default": false, + "description": "If true, the uploaded archive is not downloadable after creation. Locked at model creation; cannot be changed by subsequent deployments.", + "title": "Disable Archive Download", + "type": "boolean" } }, "required": [ - "aws_access_key_id", - "aws_secret_access_key", - "aws_session_token" + "name", + "deployment", + "s3_key" ], - "title": "AWSCredentialsV1", + "title": "ModelArchiveSourceV1", "type": "object" }, - "PrepareModelUploadResponseV1": { - "description": "Response from `POST /v1/prepare_model_upload`.\n\nOn success with `dry_run=false`, returns STS upload credentials. On success\nwith `dry_run=true`, `creds`, `s3_bucket`, and `s3_key` are `null` and only\nvalidation has run.", + "CreateModelRequestV1": { + "description": "Body for creating a model via `POST /v1/models`.", "properties": { - "creds": { + "source": { + "description": "Where the new model is created from.", + "discriminator": { + "mapping": { + "library_listing": "#/components/schemas/LibraryListingSourceV1", + "model_archive": "#/components/schemas/ModelArchiveSourceV1" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/LibraryListingSourceV1" + }, + { + "$ref": "#/components/schemas/ModelArchiveSourceV1" + } + ], + "title": "Source" + } + }, + "required": [ + "source" + ], + "title": "CreateModelRequestV1", + "type": "object" + }, + "AutoscalingSettingsV1": { + "description": "Autoscaling settings for a deployment.", + "properties": { + "min_replica": { + "description": "Minimum number of replicas", + "title": "Min Replica", + "type": "integer" + }, + "max_replica": { + "description": "Maximum number of replicas", + "title": "Max Replica", + "type": "integer" + }, + "autoscaling_window": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Timeframe of traffic considered for autoscaling decisions", + "title": "Autoscaling Window" + }, + "scale_down_delay": { "anyOf": [ { - "$ref": "#/components/schemas/AWSCredentialsV1" + "type": "integer" }, { "type": "null" } ], - "default": null, - "description": "STS credentials to upload the model archive." + "description": "Waiting period before scaling down any active replica", + "title": "Scale Down Delay" }, - "s3_bucket": { + "concurrency_target": { + "description": "Number of requests per replica before scaling up", + "title": "Concurrency Target", + "type": "integer" + }, + "target_utilization_percentage": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], - "default": null, - "description": "S3 bucket the credentials are scoped to.", - "title": "S3 Bucket" + "description": "Target utilization percentage for scaling up/down.", + "title": "Target Utilization Percentage" }, - "s3_key": { + "target_in_flight_tokens": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "S3 key the credentials are scoped to. Pass this to `POST /v1/models` (in the `model_archive` source) once the upload completes.", - "title": "S3 Key" + "description": "Target number of in-flight tokens for autoscaling decisions. Early access only.", + "title": "Target In Flight Tokens" }, - "s3_region": { + "max_scale_down_rate": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "AWS region the S3 bucket resides in.", - "title": "S3 Region" + "description": "Maximum percentage of replicas that can be removed per autoscaling window (1\u201350). E.g. 20 means at most 20% of replicas are removed per window.", + "title": "Max Scale Down Rate" } }, - "title": "PrepareModelUploadResponseV1", + "required": [ + "min_replica", + "max_replica", + "autoscaling_window", + "scale_down_delay", + "concurrency_target", + "target_utilization_percentage" + ], + "title": "AutoscalingSettingsV1", "type": "object" }, - "ModelV1": { - "description": "A model.", + "DeploymentStatusV1": { + "description": "The status of a deployment.", + "enum": [ + "BUILDING", + "DEPLOYING", + "DEPLOY_FAILED", + "LOADING_MODEL", + "ACTIVE", + "UNHEALTHY", + "BUILD_FAILED", + "BUILD_STOPPED", + "DEACTIVATING", + "INACTIVE", + "FAILED", + "UPDATING", + "SCALED_TO_ZERO", + "WAKING_UP" + ], + "title": "DeploymentStatusV1", + "type": "string" + }, + "DeploymentV1": { + "description": "A deployment of a model.", "properties": { "id": { - "description": "Unique identifier of the model", + "description": "Unique identifier of the deployment", "title": "Id", "type": "string" }, "created_at": { - "description": "Time the model was created in ISO 8601 format", + "description": "Time the deployment was created in ISO 8601 format", "format": "date-time", "title": "Created At", "type": "string" }, "name": { - "description": "Name of the model", + "description": "Name of the deployment", "title": "Name", "type": "string" }, - "deployments_count": { - "description": "Number of deployments of the model", - "title": "Deployments Count", + "model_id": { + "description": "Unique identifier of the model", + "title": "Model Id", + "type": "string" + }, + "is_production": { + "description": "Whether the deployment is the production deployment of the model", + "title": "Is Production", + "type": "boolean" + }, + "is_development": { + "description": "Whether the deployment is the development deployment of the model", + "title": "Is Development", + "type": "boolean" + }, + "status": { + "$ref": "#/components/schemas/DeploymentStatusV1", + "description": "Status of the deployment" + }, + "active_replica_count": { + "description": "Number of active replicas", + "title": "Active Replica Count", "type": "integer" }, - "production_deployment_id": { + "autoscaling_settings": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/AutoscalingSettingsV1" }, { "type": "null" } ], - "description": "Unique identifier of the production deployment of the model", - "title": "Production Deployment Id" + "description": "Autoscaling settings for the deployment. If null, the model has not finished deploying" }, - "development_deployment_id": { + "instance_type_name": { "anyOf": [ { "type": "string" @@ -6324,70 +8448,114 @@ "type": "null" } ], - "description": "Unique identifier of the development deployment of the model", - "title": "Development Deployment Id" + "description": "Name of the instance type the model deployment is running on", + "title": "Instance Type Name" }, - "instance_type_name": { - "description": "Name of the instance type for the production deployment of the model", - "title": "Instance Type Name", - "type": "string" + "environment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The environment associated with the deployment", + "title": "Environment" }, - "team_name": { - "description": "Name of the team associated with the model.", - "title": "Team Name", - "type": "string" + "labels": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "User-provided key-value labels for the deployment", + "title": "Labels" } }, "required": [ "id", "created_at", "name", - "deployments_count", - "production_deployment_id", - "development_deployment_id", + "model_id", + "is_production", + "is_development", + "status", + "active_replica_count", + "autoscaling_settings", "instance_type_name", - "team_name" + "environment" ], - "title": "ModelV1", + "title": "DeploymentV1", "type": "object" }, - "ModelsV1": { - "description": "A list of models.", + "CreatedModelDeploymentV1": { + "description": "A newly created deployment and its model.", "properties": { - "models": { + "model": { + "$ref": "#/components/schemas/ModelV1", + "description": "The model the deployment belongs to. May have been created by this call." + }, + "deployment": { + "$ref": "#/components/schemas/DeploymentV1", + "description": "The newly created deployment." + } + }, + "required": [ + "model", + "deployment" + ], + "title": "CreatedModelDeploymentV1", + "type": "object" + }, + "ModelTombstoneV1": { + "description": "A model tombstone.", + "properties": { + "id": { + "description": "Unique identifier of the model", + "title": "Id", + "type": "string" + }, + "deleted": { + "description": "Whether the model was deleted", + "title": "Deleted", + "type": "boolean" + } + }, + "required": [ + "id", + "deleted" + ], + "title": "ModelTombstoneV1", + "type": "object" + }, + "DeploymentsV1": { + "description": "A list of deployments of a model.", + "properties": { + "deployments": { + "description": "A list of deployments of a model", "items": { - "$ref": "#/components/schemas/ModelV1" + "$ref": "#/components/schemas/DeploymentV1" }, - "title": "Models", + "title": "Deployments", "type": "array" } }, "required": [ - "models" + "deployments" ], - "title": "ModelsV1", + "title": "DeploymentsV1", "type": "object" }, - "LibraryListingSourceV1": { - "description": "Create a model by forking a library listing accessible to the caller's organization.", + "DeploymentsRequestV1": { + "description": "Request parameters for listing a model's deployments.", "properties": { - "kind": { - "const": "library_listing", - "default": "library_listing", - "title": "Kind", - "type": "string" - }, - "lab_display_name": { - "description": "Identifier of the publishing organization, as returned by `GET /v1/library_models`.", - "title": "Lab Display Name", - "type": "string" - }, - "user_defined_listing_id": { - "description": "Listing identifier within the publishing organization.", - "title": "User Defined Listing Id", - "type": "string" - }, - "deployed_model_name": { + "name": { "anyOf": [ { "type": "string" @@ -6397,19 +8565,15 @@ } ], "default": null, - "description": "Optional name for the new deployed model. Defaults to the listing's configured name.", - "title": "Deployed Model Name" + "description": "When set, returns only the deployment with this exact name, if any.", + "title": "Name" } }, - "required": [ - "lab_display_name", - "user_defined_listing_id" - ], - "title": "LibraryListingSourceV1", + "title": "DeploymentsRequestV1", "type": "object" }, - "ModelArchiveSourceV1": { - "description": "Create a model from an archive previously uploaded via the credentials\nissued by `POST /v1/prepare_model_upload`.", + "DeploymentArchiveSourceV1": { + "description": "Add a deployment from an archive previously uploaded via the credentials\nissued by `POST /v1/prepare_model_upload`.", "properties": { "kind": { "const": "model_archive", @@ -6417,59 +8581,37 @@ "title": "Kind", "type": "string" }, - "name": { - "description": "Name of the new model.", - "title": "Name", - "type": "string" - }, "deployment": { "$ref": "#/components/schemas/DeploymentArchivePayloadV1", - "description": "Deployment-level configuration for the model's first deployment." + "description": "Deployment-level configuration." }, "s3_key": { "description": "S3 key of the uploaded archive, from the credentials returned by `POST /v1/prepare_model_upload`.", "title": "S3 Key", "type": "string" - }, - "disable_archive_download": { - "default": false, - "description": "If true, the uploaded archive is not downloadable after creation. Locked at model creation; cannot be changed by subsequent deployments.", - "title": "Disable Archive Download", - "type": "boolean" - }, - "is_development": { - "default": false, - "description": "If true, push as a development deployment (the model's single mutable dev slot; overwrites any existing development deployment). The following `deployment` fields must be left at their defaults: `environment_name`, `preserve_env_instance_type`, `deployment_name`.", - "title": "Is Development", - "type": "boolean" } }, "required": [ - "name", "deployment", "s3_key" ], - "title": "ModelArchiveSourceV1", + "title": "DeploymentArchiveSourceV1", "type": "object" }, - "CreateModelRequestV1": { - "description": "Body for creating a model via `POST /v1/models`.", + "CreateModelDeploymentRequestV1": { + "description": "Body for adding a deployment to an existing model via\n`POST /v1/models/{model_id}/deployments`.", "properties": { "source": { - "description": "Where the new model is created from.", + "description": "Where the new deployment is created from.", "discriminator": { "mapping": { - "library_listing": "#/components/schemas/LibraryListingSourceV1", - "model_archive": "#/components/schemas/ModelArchiveSourceV1" + "model_archive": "#/components/schemas/DeploymentArchiveSourceV1" }, "propertyName": "kind" }, "oneOf": [ { - "$ref": "#/components/schemas/LibraryListingSourceV1" - }, - { - "$ref": "#/components/schemas/ModelArchiveSourceV1" + "$ref": "#/components/schemas/DeploymentArchiveSourceV1" } ], "title": "Source" @@ -6478,21 +8620,71 @@ "required": [ "source" ], - "title": "CreateModelRequestV1", + "title": "CreateModelDeploymentRequestV1", "type": "object" }, - "AutoscalingSettingsV1": { - "description": "Autoscaling settings for a deployment.", + "DeploymentTombstoneV1": { + "description": "A model deployment tombstone.", + "properties": { + "id": { + "description": "Unique identifier of the deployment", + "title": "Id", + "type": "string" + }, + "deleted": { + "description": "Whether the deployment was deleted", + "title": "Deleted", + "type": "boolean" + }, + "model_id": { + "description": "Unique identifier of the model", + "title": "Model Id", + "type": "string" + } + }, + "required": [ + "id", + "deleted", + "model_id" + ], + "title": "DeploymentTombstoneV1", + "type": "object" + }, + "UpdateAutoscalingSettingsV1": { + "additionalProperties": false, + "description": "A request to update autoscaling settings for a deployment. All fields are optional, and we only update ones passed in.", "properties": { "min_replica": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, "description": "Minimum number of replicas", - "title": "Min Replica", - "type": "integer" + "examples": [ + 0 + ], + "title": "Min Replica" }, "max_replica": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, "description": "Maximum number of replicas", - "title": "Max Replica", - "type": "integer" + "examples": [ + 7 + ], + "title": "Max Replica" }, "autoscaling_window": { "anyOf": [ @@ -6503,7 +8695,11 @@ "type": "null" } ], + "default": null, "description": "Timeframe of traffic considered for autoscaling decisions", + "examples": [ + 600 + ], "title": "Autoscaling Window" }, "scale_down_delay": { @@ -6515,13 +8711,28 @@ "type": "null" } ], + "default": null, "description": "Waiting period before scaling down any active replica", + "examples": [ + 120 + ], "title": "Scale Down Delay" }, "concurrency_target": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, "description": "Number of requests per replica before scaling up", - "title": "Concurrency Target", - "type": "integer" + "examples": [ + 2 + ], + "title": "Concurrency Target" }, "target_utilization_percentage": { "anyOf": [ @@ -6532,7 +8743,11 @@ "type": "null" } ], + "default": null, "description": "Target utilization percentage for scaling up/down.", + "examples": [ + 70 + ], "title": "Target Utilization Percentage" }, "target_in_flight_tokens": { @@ -6546,109 +8761,123 @@ ], "default": null, "description": "Target number of in-flight tokens for autoscaling decisions. Early access only.", + "examples": [ + 40000 + ], "title": "Target In Flight Tokens" }, "max_scale_down_rate": { "anyOf": [ { - "type": "number" + "maximum": 50, + "minimum": 1, + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Maximum rate at which replicas can scale down (e.g. 2.0 means at most halve replicas per window).", + "description": "Maximum percentage of replicas that can be removed per autoscaling window (1\u201350). E.g. 20 means at most 20% of replicas are removed per window.", + "examples": [ + 20 + ], "title": "Max Scale Down Rate" } }, - "required": [ - "min_replica", - "max_replica", - "autoscaling_window", - "scale_down_delay", - "concurrency_target", - "target_utilization_percentage" - ], - "title": "AutoscalingSettingsV1", + "title": "UpdateAutoscalingSettingsV1", "type": "object" }, - "DeploymentStatusV1": { - "description": "The status of a deployment.", + "UpdateAutoscalingSettingsStatusV1": { + "description": "The status of a request to update autoscaling settings.", "enum": [ - "BUILDING", - "DEPLOYING", - "DEPLOY_FAILED", - "LOADING_MODEL", - "ACTIVE", - "UNHEALTHY", - "BUILD_FAILED", - "BUILD_STOPPED", - "DEACTIVATING", - "INACTIVE", - "FAILED", - "UPDATING", - "SCALED_TO_ZERO", - "WAKING_UP" + "ACCEPTED", + "QUEUED", + "UNCHANGED" ], - "title": "DeploymentStatusV1", + "title": "UpdateAutoscalingSettingsStatusV1", "type": "string" }, - "DeploymentV1": { - "description": "A deployment of a model.", + "UpdateAutoscalingSettingsResponseV1": { + "description": "The response to a request to update autoscaling settings.", "properties": { - "id": { - "description": "Unique identifier of the deployment", - "title": "Id", - "type": "string" - }, - "created_at": { - "description": "Time the deployment was created in ISO 8601 format", - "format": "date-time", - "title": "Created At", - "type": "string" - }, - "name": { - "description": "Name of the deployment", - "title": "Name", - "type": "string" + "status": { + "$ref": "#/components/schemas/UpdateAutoscalingSettingsStatusV1", + "description": "Status of the request to update autoscaling settings" }, - "model_id": { - "description": "Unique identifier of the model", - "title": "Model Id", + "message": { + "description": "A message describing the status of the request to update autoscaling settings", + "title": "Message", "type": "string" - }, - "is_production": { - "description": "Whether the deployment is the production deployment of the model", - "title": "Is Production", + } + }, + "required": [ + "status", + "message" + ], + "title": "UpdateAutoscalingSettingsResponseV1", + "type": "object" + }, + "PromoteRequestV1": { + "description": "A request to promote a deployment to production.", + "properties": { + "scale_down_previous_production": { + "default": true, + "description": "Whether to scale down the previous production deployment after promoting", + "examples": [ + true + ], + "title": "Scale Down Previous Production", "type": "boolean" }, - "is_development": { - "description": "Whether the deployment is the development deployment of the model", - "title": "Is Development", + "preserve_env_instance_type": { + "default": true, + "description": "Whether to use the promoting deployment's instance type or preserve target environment's instance type", + "examples": [ + true + ], + "title": "Preserve Env Instance Type", + "type": "boolean" + } + }, + "title": "PromoteRequestV1", + "type": "object" + }, + "ActivateResponseV1": { + "description": "The response to a request to activate a deployment.", + "properties": { + "success": { + "default": true, + "description": "Whether the deployment was successfully activated", + "title": "Success", + "type": "boolean" + } + }, + "title": "ActivateResponseV1", + "type": "object" + }, + "DeactivateResponseV1": { + "description": "The response to a request to deactivate a deployment.", + "properties": { + "success": { + "default": true, + "description": "Whether the deployment was successfully deactivated", + "title": "Success", + "type": "boolean" + } + }, + "title": "DeactivateResponseV1", + "type": "object" + }, + "RetryDeploymentResponseV1": { + "description": "The response to a request to retry a deployment.", + "properties": { + "retried": { + "description": "Whether the retry was successfully initiated", + "title": "Retried", "type": "boolean" }, - "status": { - "$ref": "#/components/schemas/DeploymentStatusV1", - "description": "Status of the deployment" - }, - "active_replica_count": { - "description": "Number of active replicas", - "title": "Active Replica Count", - "type": "integer" - }, - "autoscaling_settings": { - "anyOf": [ - { - "$ref": "#/components/schemas/AutoscalingSettingsV1" - }, - { - "type": "null" - } - ], - "description": "Autoscaling settings for the deployment. If null, the model has not finished deploying" - }, - "instance_type_name": { + "reason": { "anyOf": [ { "type": "string" @@ -6657,193 +8886,191 @@ "type": "null" } ], - "description": "Name of the instance type the model deployment is running on", - "title": "Instance Type Name" + "default": null, + "description": "Explanation of the result. Provided when retried is false to explain why retry was not possible.", + "title": "Reason" }, - "environment": { + "deployment": { + "$ref": "#/components/schemas/DeploymentV1", + "description": "The deployment that was retried" + } + }, + "required": [ + "retried", + "deployment" + ], + "title": "RetryDeploymentResponseV1", + "type": "object" + }, + "DownloadDeploymentResponseV1": { + "description": "The response to a request to download a deployment's truss.", + "properties": { + "download_url": { + "description": "Presigned URL to download the truss tar file", + "title": "Download Url", + "type": "string" + } + }, + "required": [ + "download_url" + ], + "title": "DownloadDeploymentResponseV1", + "type": "object" + }, + "DeploymentConfigResponseV1": { + "description": "The config of a deployment. Fields are populated per `output_format`.", + "properties": { + "config": { "anyOf": [ { - "type": "string" + "additionalProperties": true, + "type": "object" }, { "type": "null" } ], - "description": "The environment associated with the deployment", - "title": "Environment" + "default": null, + "description": "The parsed config of the deployment.", + "title": "Config" }, - "labels": { + "raw_config": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "User-provided key-value labels for the deployment", - "title": "Labels" + "description": "The original config.yaml text \u2014 preserves comments, ordering, formatting.", + "title": "Raw Config" } }, - "required": [ - "id", - "created_at", - "name", - "model_id", - "is_production", - "is_development", - "status", - "active_replica_count", - "autoscaling_settings", - "instance_type_name", - "environment" - ], - "title": "DeploymentV1", + "title": "DeploymentConfigResponseV1", "type": "object" }, - "CreatedModelDeploymentV1": { - "description": "A newly created deployment and its model.", - "properties": { - "model": { - "$ref": "#/components/schemas/ModelV1", - "description": "The model the deployment belongs to. May have been created by this call." - }, - "deployment": { - "$ref": "#/components/schemas/DeploymentV1", - "description": "The newly created deployment." - } - }, - "required": [ - "model", - "deployment" + "DeploymentConfigOutputFormat": { + "enum": [ + "raw", + "parsed", + "both" ], - "title": "CreatedModelDeploymentV1", - "type": "object" + "title": "DeploymentConfigOutputFormat", + "type": "string" }, - "ModelTombstoneV1": { - "description": "A model tombstone.", + "GetDeploymentConfigRequestV1": { + "description": "Query params for ``GET /v1/models/.../deployments/.../config``.", "properties": { - "id": { - "description": "Unique identifier of the model", - "title": "Id", - "type": "string" - }, - "deleted": { - "description": "Whether the model was deleted", - "title": "Deleted", - "type": "boolean" + "output_format": { + "$ref": "#/components/schemas/DeploymentConfigOutputFormat", + "default": "both", + "description": "'raw': verbatim config.yaml with comments (not available for deployments created before 2026-04-30). 'parsed': dict with server-side defaults applied (always available). 'both': both fields populated." } }, - "required": [ - "id", - "deleted" - ], - "title": "ModelTombstoneV1", + "title": "GetDeploymentConfigRequestV1", "type": "object" }, - "DeploymentsV1": { - "description": "A list of deployments of a model.", - "properties": { - "deployments": { - "description": "A list of deployments of a model", - "items": { - "$ref": "#/components/schemas/DeploymentV1" - }, - "title": "Deployments", - "type": "array" - } - }, - "required": [ - "deployments" + "LogLevelV1": { + "description": "A log severity level.", + "enum": [ + "DEBUG", + "INFO", + "WARNING", + "ERROR" ], - "title": "DeploymentsV1", - "type": "object" + "title": "LogLevelV1", + "type": "string" }, - "DeploymentArchiveSourceV1": { - "description": "Add a deployment from an archive previously uploaded via the credentials\nissued by `POST /v1/prepare_model_upload`.", + "LogV1": { "properties": { - "kind": { - "const": "model_archive", - "default": "model_archive", - "title": "Kind", + "timestamp": { + "description": "Epoch nanosecond timestamp of the log message.", + "title": "Timestamp", "type": "string" }, - "deployment": { - "$ref": "#/components/schemas/DeploymentArchivePayloadV1", - "description": "Deployment-level configuration." - }, - "s3_key": { - "description": "S3 key of the uploaded archive, from the credentials returned by `POST /v1/prepare_model_upload`.", - "title": "S3 Key", + "message": { + "description": "The contents of the log message.", + "title": "Message", "type": "string" - } - }, - "required": [ - "deployment", - "s3_key" - ], - "title": "DeploymentArchiveSourceV1", - "type": "object" - }, - "CreateModelDeploymentRequestV1": { - "description": "Body for adding a deployment to an existing model via\n`POST /v1/models/{model_id}/deployments`.", - "properties": { - "source": { - "description": "Where the new deployment is created from.", - "discriminator": { - "mapping": { - "model_archive": "#/components/schemas/DeploymentArchiveSourceV1" + }, + "replica": { + "anyOf": [ + { + "type": "string" }, - "propertyName": "kind" - }, - "oneOf": [ { - "$ref": "#/components/schemas/DeploymentArchiveSourceV1" + "type": "null" } ], - "title": "Source" + "description": "The replica the log line was emitted from.", + "title": "Replica" + }, + "request_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The request ID associated with an inference request.", + "title": "Request Id" + }, + "level": { + "anyOf": [ + { + "$ref": "#/components/schemas/LogLevelV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Severity of the log line, if one was detected. null when unknown." } }, "required": [ - "source" + "timestamp", + "message", + "replica" ], - "title": "CreateModelDeploymentRequestV1", + "title": "LogV1", "type": "object" }, - "DeploymentTombstoneV1": { - "description": "A model deployment tombstone.", - "properties": { - "id": { - "description": "Unique identifier of the deployment", - "title": "Id", - "type": "string" - }, - "deleted": { - "description": "Whether the deployment was deleted", - "title": "Deleted", - "type": "boolean" - }, - "model_id": { - "description": "Unique identifier of the model", - "title": "Model Id", - "type": "string" + "GetLogsResponseV1": { + "description": "A response to querying logs.", + "properties": { + "logs": { + "description": "Logs for a specific entity.", + "items": { + "$ref": "#/components/schemas/LogV1" + }, + "title": "Logs", + "type": "array" } }, "required": [ - "id", - "deleted", - "model_id" + "logs" ], - "title": "DeploymentTombstoneV1", + "title": "GetLogsResponseV1", "type": "object" }, - "UpdateAutoscalingSettingsV1": { - "additionalProperties": false, - "description": "A request to update autoscaling settings for a deployment. All fields are optional, and we only update ones passed in.", + "SortOrderV1": { + "enum": [ + "asc", + "desc" + ], + "title": "SortOrderV1", + "type": "string" + }, + "GetDeploymentLogsRequestV1": { + "description": "A request to fetch deployment logs.", "properties": { - "min_replica": { + "start_epoch_millis": { "anyOf": [ { "type": "integer" @@ -6853,13 +9080,10 @@ } ], "default": null, - "description": "Minimum number of replicas", - "examples": [ - 0 - ], - "title": "Min Replica" + "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + "title": "Start Epoch Millis" }, - "max_replica": { + "end_epoch_millis": { "anyOf": [ { "type": "integer" @@ -6869,204 +9093,251 @@ } ], "default": null, - "description": "Maximum number of replicas", - "examples": [ - 7 - ], - "title": "Max Replica" + "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + "title": "End Epoch Millis" }, - "autoscaling_window": { + "direction": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/SortOrderV1" }, { "type": "null" } ], "default": null, - "description": "Timeframe of traffic considered for autoscaling decisions", - "examples": [ - 600 - ], - "title": "Autoscaling Window" + "description": "Sort order for logs" }, - "scale_down_delay": { + "limit": { "anyOf": [ { + "maximum": 1000, + "minimum": 1, "type": "integer" }, { "type": "null" } ], - "default": null, - "description": "Waiting period before scaling down any active replica", - "examples": [ - 120 - ], - "title": "Scale Down Delay" + "default": 500, + "description": "Limit of logs to fetch in a single request", + "title": "Limit" }, - "concurrency_target": { + "min_level": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/LogLevelV1" }, { "type": "null" } ], "default": null, - "description": "Number of requests per replica before scaling up", - "examples": [ - 2 - ], - "title": "Concurrency Target" + "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." }, - "target_utilization_percentage": { + "replica": { "anyOf": [ { - "type": "integer" + "maxLength": 256, + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Target utilization percentage for scaling up/down.", - "examples": [ - 70 - ], - "title": "Target Utilization Percentage" + "description": "Only return logs emitted by this replica (5-char short ID).", + "title": "Replica" }, - "target_in_flight_tokens": { + "request_id": { "anyOf": [ { - "type": "integer" + "maxLength": 256, + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Target number of in-flight tokens for autoscaling decisions. Early access only.", - "examples": [ - 40000 - ], - "title": "Target In Flight Tokens" + "description": "Only return logs tagged with this inference request ID.", + "title": "Request Id" }, - "max_scale_down_rate": { + "component": { "anyOf": [ { - "exclusiveMinimum": 1, - "maximum": 2, - "type": "number" + "maxLength": 256, + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Maximum rate at which replicas can scale down (e.g. 2.0 means at most halve replicas per window).", - "examples": [ - 2.0 + "description": "Only return logs from this component.", + "title": "Component" + }, + "search_pattern": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } ], - "title": "Max Scale Down Rate" + "default": null, + "description": "RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", + "title": "Search Pattern" + }, + "includes": { + "description": "Case-sensitive substrings that must all appear in the log message.", + "items": { + "type": "string" + }, + "maxItems": 8, + "title": "Includes", + "type": "array" + }, + "excludes": { + "description": "Case-sensitive substrings; lines containing any of these are dropped.", + "items": { + "type": "string" + }, + "maxItems": 8, + "title": "Excludes", + "type": "array" } }, - "title": "UpdateAutoscalingSettingsV1", + "title": "GetDeploymentLogsRequestV1", "type": "object" }, - "UpdateAutoscalingSettingsStatusV1": { - "description": "The status of a request to update autoscaling settings.", + "DeploymentPatchActionV1": { + "description": "How a patch op changes its target.", "enum": [ - "ACCEPTED", - "QUEUED", - "UNCHANGED" + "ADD", + "UPDATE", + "REMOVE" ], - "title": "UpdateAutoscalingSettingsStatusV1", + "title": "DeploymentPatchActionV1", "type": "string" }, - "UpdateAutoscalingSettingsResponseV1": { - "description": "The response to a request to update autoscaling settings.", + "DeploymentPatchOpConfigV1": { + "description": "Replace the config when config.yaml changes.\n\nConfig has no action: it is always a full replacement of the parsed config.\nDerived changes (environment variables, external data, requirements) are\nemitted as their own ops alongside this one.", "properties": { - "status": { - "$ref": "#/components/schemas/UpdateAutoscalingSettingsStatusV1", - "description": "Status of the request to update autoscaling settings" + "type": { + "const": "config", + "default": "config", + "title": "Type", + "type": "string" }, - "message": { - "description": "A message describing the status of the request to update autoscaling settings", - "title": "Message", + "config": { + "additionalProperties": true, + "description": "The full parsed config as a JSON object.", + "title": "Config", + "type": "object" + }, + "path": { + "default": "config.yaml", + "description": "Config file path within the source.", + "title": "Path", "type": "string" } }, "required": [ - "status", - "message" + "config" ], - "title": "UpdateAutoscalingSettingsResponseV1", + "title": "DeploymentPatchOpConfigV1", "type": "object" }, - "PromoteRequestV1": { - "description": "A request to promote a deployment to production.", + "DeploymentPatchOpEnvVarV1": { + "description": "Add, update, or remove a single environment variable.", "properties": { - "scale_down_previous_production": { - "default": true, - "description": "Whether to scale down the previous production deployment after promoting", - "examples": [ - true - ], - "title": "Scale Down Previous Production", - "type": "boolean" + "type": { + "const": "environment_variable", + "default": "environment_variable", + "title": "Type", + "type": "string" }, - "preserve_env_instance_type": { - "default": true, - "description": "Whether to use the promoting deployment's instance type or preserve target environment's instance type", - "examples": [ - true + "action": { + "$ref": "#/components/schemas/DeploymentPatchActionV1", + "description": "How this op changes the variable." + }, + "name": { + "description": "The environment variable name.", + "title": "Name", + "type": "string" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } ], - "title": "Preserve Env Instance Type", - "type": "boolean" - } - }, - "title": "PromoteRequestV1", - "type": "object" - }, - "ActivateResponseV1": { - "description": "The response to a request to activate a deployment.", - "properties": { - "success": { - "default": true, - "description": "Whether the deployment was successfully activated", - "title": "Success", - "type": "boolean" + "default": null, + "description": "The environment variable value. Required for add and update.", + "title": "Value" } }, - "title": "ActivateResponseV1", + "required": [ + "action", + "name" + ], + "title": "DeploymentPatchOpEnvVarV1", "type": "object" }, - "DeactivateResponseV1": { - "description": "The response to a request to deactivate a deployment.", + "DeploymentPatchOpExternalDataV1": { + "description": "Add, update, or remove a single external data item.\n\nExternal data is referenced by config, not stored in the source. The backend\nonly adds or removes it, where adding re-downloads (overwriting any existing\nfile), so `update` is accepted and treated identically to `add`.", "properties": { - "success": { - "default": true, - "description": "Whether the deployment was successfully deactivated", - "title": "Success", - "type": "boolean" + "type": { + "const": "external_data", + "default": "external_data", + "title": "Type", + "type": "string" + }, + "action": { + "$ref": "#/components/schemas/DeploymentPatchActionV1", + "description": "How this op changes the item. `UPDATE` is treated identically to `ADD`." + }, + "item": { + "additionalProperties": { + "type": "string" + }, + "description": "The single external data item descriptor.", + "title": "Item", + "type": "object" } }, - "title": "DeactivateResponseV1", + "required": [ + "action", + "item" + ], + "title": "DeploymentPatchOpExternalDataV1", "type": "object" }, - "RetryDeploymentResponseV1": { - "description": "The response to a request to retry a deployment.", + "DeploymentPatchOpModelCodeV1": { + "description": "Add, update, or remove a file under the model code directory.", "properties": { - "retried": { - "description": "Whether the retry was successfully initiated", - "title": "Retried", - "type": "boolean" + "type": { + "const": "model_code", + "default": "model_code", + "title": "Type", + "type": "string" }, - "reason": { + "action": { + "$ref": "#/components/schemas/DeploymentPatchActionV1", + "description": "How this op changes the file." + }, + "path": { + "description": "File path relative to the model code directory.", + "title": "Path", + "type": "string" + }, + "content": { "anyOf": [ { "type": "string" @@ -7076,54 +9347,68 @@ } ], "default": null, - "description": "Explanation of the result. Provided when retried is false to explain why retry was not possible.", - "title": "Reason" + "description": "UTF-8 file content. Null for removals and binary files.", + "title": "Content" }, - "deployment": { - "$ref": "#/components/schemas/DeploymentV1", - "description": "The deployment that was retried" - } - }, - "required": [ - "retried", - "deployment" - ], - "title": "RetryDeploymentResponseV1", - "type": "object" - }, - "DownloadDeploymentResponseV1": { - "description": "The response to a request to download a deployment's truss.", - "properties": { - "download_url": { - "description": "Presigned URL to download the truss tar file", - "title": "Download Url", - "type": "string" + "content_bytes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Base64-encoded content for binary files.", + "title": "Content Bytes" + }, + "hot_reload": { + "default": false, + "description": "Whether the running server can pick up this change without a restart.", + "title": "Hot Reload", + "type": "boolean" } }, "required": [ - "download_url" + "action", + "path" ], - "title": "DownloadDeploymentResponseV1", + "title": "DeploymentPatchOpModelCodeV1", "type": "object" }, - "DeploymentConfigResponseV1": { - "description": "The config of a deployment. Fields are populated per `output_format`.", + "DeploymentPatchOpPackageV1": { + "description": "Add, update, or remove a file under the bundled packages directory.", "properties": { - "config": { + "type": { + "const": "package", + "default": "package", + "title": "Type", + "type": "string" + }, + "action": { + "$ref": "#/components/schemas/DeploymentPatchActionV1", + "description": "How this op changes the file." + }, + "path": { + "description": "File path relative to the bundled packages directory.", + "title": "Path", + "type": "string" + }, + "content": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "The parsed config of the deployment.", - "title": "Config" + "description": "UTF-8 file content. Null for removals and binary files.", + "title": "Content" }, - "raw_config": { + "content_bytes": { "anyOf": [ { "type": "string" @@ -7133,59 +9418,237 @@ } ], "default": null, - "description": "The original config.yaml text \u2014 preserves comments, ordering, formatting.", - "title": "Raw Config" + "description": "Base64-encoded content for binary files.", + "title": "Content Bytes" } }, - "title": "DeploymentConfigResponseV1", + "required": [ + "action", + "path" + ], + "title": "DeploymentPatchOpPackageV1", "type": "object" }, - "DeploymentConfigOutputFormat": { - "enum": [ - "raw", - "parsed", - "both" + "DeploymentPatchOpPythonRequirementV1": { + "description": "Add, update, or remove a single Python requirement.", + "properties": { + "type": { + "const": "python_requirement", + "default": "python_requirement", + "title": "Type", + "type": "string" + }, + "action": { + "$ref": "#/components/schemas/DeploymentPatchActionV1", + "description": "How this op changes the requirement." + }, + "requirement": { + "description": "The requirement to apply. For removals this is the package name; otherwise the full requirements.txt-style line.", + "title": "Requirement", + "type": "string" + } + }, + "required": [ + "action", + "requirement" ], - "title": "DeploymentConfigOutputFormat", - "type": "string" + "title": "DeploymentPatchOpPythonRequirementV1", + "type": "object" }, - "GetDeploymentConfigRequestV1": { - "description": "Query params for ``GET /v1/models/.../deployments/.../config``.", + "DeploymentPatchPointV1": { + "description": "A patch point: the source state the next patch is computed against.\n\nThe content hash that identifies a point is derived from this state (see\n`DeploymentPatchPointWithHashV1.hash`), so a request only sends the state and\nthe server stamps the hash. A previous point's hash plus the current local\nsource is enough to compute the next patch, so the watch client reads the\npoint it is patching off of.", "properties": { - "output_format": { - "$ref": "#/components/schemas/DeploymentConfigOutputFormat", - "default": "both", - "description": "'raw': verbatim config.yaml with comments \u2014 not available for deployments created before 2026-04-30. 'parsed': dict with server-side defaults applied \u2014 always available. 'both': both fields populated." + "content_hashes": { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "description": "Map of every non-ignored source path, relative and forward-slash, to its content hash: files map to the hex blake3 digest of their bytes, directories map to null. This is the full signature of the source tree and what the content hash is derived from.", + "title": "Content Hashes", + "type": "object" + }, + "config": { + "description": "The verbatim config.yaml text for this source state.", + "title": "Config", + "type": "string" + }, + "requirements": { + "description": "Requirements resolved from the config's requirements file, when it points at one. Empty when requirements are declared inline in the config.", + "items": { + "type": "string" + }, + "title": "Requirements", + "type": "array" } }, - "title": "GetDeploymentConfigRequestV1", + "required": [ + "content_hashes", + "config" + ], + "title": "DeploymentPatchPointV1", "type": "object" }, - "LogV1": { + "CreateDeploymentPatchRequestV1": { + "description": "A patch to stage against the development deployment.\n\nStaging is durable on its own: the patch is persisted independently of the\nlater sync, so a failed sync does not lose it.", "properties": { - "timestamp": { - "description": "Epoch nanosecond timestamp of the log message.", - "title": "Timestamp", + "prev_patch_hash": { + "description": "Content hash of the patch point this patch is applied on - the link the staged patch must build on. A stale value (the base moved underneath the client) is rejected with a conflict.", + "title": "Prev Patch Hash", "type": "string" }, - "message": { - "description": "The contents of the log message.", - "title": "Message", + "next_patch_point": { + "$ref": "#/components/schemas/DeploymentPatchPointV1", + "description": "The source state after this patch. The server derives its content hash from `content_hashes`." + }, + "patch_ops": { + "description": "The ordered ops that make up this patch. At least one op is required; a patch that changes nothing is not a valid request. There is no op for a directory: a directory comes into existence when the first file under it is added, and is removed when its last file is removed, so directory creation and deletion happen implicitly through the file ops. Adding or removing an otherwise empty directory therefore produces no ops even though it changes the source hash; do not send a patch request for such a change.", + "items": { + "discriminator": { + "mapping": { + "config": "#/components/schemas/DeploymentPatchOpConfigV1", + "environment_variable": "#/components/schemas/DeploymentPatchOpEnvVarV1", + "external_data": "#/components/schemas/DeploymentPatchOpExternalDataV1", + "model_code": "#/components/schemas/DeploymentPatchOpModelCodeV1", + "package": "#/components/schemas/DeploymentPatchOpPackageV1", + "python_requirement": "#/components/schemas/DeploymentPatchOpPythonRequirementV1" + }, + "propertyName": "type" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/DeploymentPatchOpModelCodeV1" + }, + { + "$ref": "#/components/schemas/DeploymentPatchOpPackageV1" + }, + { + "$ref": "#/components/schemas/DeploymentPatchOpConfigV1" + }, + { + "$ref": "#/components/schemas/DeploymentPatchOpPythonRequirementV1" + }, + { + "$ref": "#/components/schemas/DeploymentPatchOpEnvVarV1" + }, + { + "$ref": "#/components/schemas/DeploymentPatchOpExternalDataV1" + } + ] + }, + "minItems": 1, + "title": "Patch Ops", + "type": "array" + } + }, + "required": [ + "prev_patch_hash", + "next_patch_point", + "patch_ops" + ], + "title": "CreateDeploymentPatchRequestV1", + "type": "object" + }, + "DeploymentPatchPointWithHashV1": { + "description": "A patch point plus its server-assigned content hash, returned in responses.\n\nRequests omit the hash (the server derives it from the source state); responses\ninclude it so the watch client can echo it back as the next patch's\n`prev_patch_hash` without having to recompute the fold itself.", + "properties": { + "content_hashes": { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "description": "Map of every non-ignored source path, relative and forward-slash, to its content hash: files map to the hex blake3 digest of their bytes, directories map to null. This is the full signature of the source tree and what the content hash is derived from.", + "title": "Content Hashes", + "type": "object" + }, + "config": { + "description": "The verbatim config.yaml text for this source state.", + "title": "Config", "type": "string" }, - "replica": { + "requirements": { + "description": "Requirements resolved from the config's requirements file, when it points at one. Empty when requirements are declared inline in the config.", + "items": { + "type": "string" + }, + "title": "Requirements", + "type": "array" + }, + "hash": { + "description": "Content hash identifying this exact source state, and the link patches build on. It is derived deterministically from `content_hashes`, so a request need not send it - the server derives it. It is derived by sorting the `content_hashes` keys as paths, splitting each key on '/' into its path components and ordering the keys by comparing those component lists element by element, each component compared by Unicode code point (equivalently UTF-8 byte order). Treating '/' as a path separator this way, rather than as the ordinary character U+002F, means a key that is an ancestor path sorts before a sibling whose name extends the first differing component (so e.g. 'a/b' sorts before 'a.b'). A blake3 hasher is then built, and for each key in that order updated with the blake3 digest (32 raw bytes) of the key encoded as UTF-8, then, when the entry is a file (non-null value), with that file's digest as 32 raw bytes. The stream uses raw digest bytes, but the values in `content_hashes` are those digests hex-encoded (64 hex chars), so decode each value from hex first. Directory entries (null value) contribute only their key digest. The result is the hasher's own hex digest.", + "title": "Hash", + "type": "string" + } + }, + "required": [ + "content_hashes", + "config", + "hash" + ], + "title": "DeploymentPatchPointWithHashV1", + "type": "object" + }, + "CreateDeploymentPatchResponseV1": { + "description": "The created patch, represented by the patch point it produced.", + "properties": { + "patch_point": { + "$ref": "#/components/schemas/DeploymentPatchPointWithHashV1", + "description": "The resulting patch point the staged patch produced; matches the pending point a subsequent state read returns." + } + }, + "required": [ + "patch_point" + ], + "title": "CreateDeploymentPatchResponseV1", + "type": "object" + }, + "GetDeploymentPatchesStateResponseV1": { + "description": "The patch state of the development deployment.\n\nThe watch client computes its next patch off `pending_patch_point` when present,\nelse `running_patch_point`.", + "properties": { + "running_patch_point": { + "$ref": "#/components/schemas/DeploymentPatchPointWithHashV1", + "description": "The patch point the deployment is recorded as running." + }, + "pending_patch_point": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/DeploymentPatchPointWithHashV1" }, { "type": "null" } ], - "description": "The replica the log line was emitted from.", - "title": "Replica" - }, - "request_id": { + "default": null, + "description": "The latest staged-but-unsynced patch point, or null when the deployment is recorded as caught up." + } + }, + "required": [ + "running_patch_point" + ], + "title": "GetDeploymentPatchesStateResponseV1", + "type": "object" + }, + "SyncDeploymentPatchesRequestV1": { + "description": "Triggers a sync of any staged patches to the running deployment. Takes no\nfields: the deployment and its staged patches fully determine the sync.", + "properties": {}, + "title": "SyncDeploymentPatchesRequestV1", + "type": "object" + }, + "SyncDeploymentPatchesResponseV1": { + "description": "The outcome of a sync that ran.\n\nOperational failures (a transient patch failure, an invalid patch sequence)\nare surfaced as HTTP errors rather than fields here, so a 2xx means the sync\nreached a verdict.", + "properties": { + "needs_full_deploy_reason": { "anyOf": [ { "type": "string" @@ -7195,61 +9658,135 @@ } ], "default": null, - "description": "The request ID associated with an inference request.", - "title": "Request Id" + "description": "If set, the change cannot be patched and a full push is required; the value explains why. If null, the deployment is now in sync.", + "title": "Needs Full Deploy Reason" } }, - "required": [ - "timestamp", - "message", - "replica" - ], - "title": "LogV1", + "title": "SyncDeploymentPatchesResponseV1", "type": "object" }, - "GetLogsResponseV1": { - "description": "A response to querying logs.", + "ModelMetricDescriptorV1": { + "description": "Describes one metric. Its position in the response ``metric_descriptors``\nlist is the index used to read that metric out of each value set's ``values``.\n\nA metric may break down into multiple labeled series (e.g. latency quantiles,\nor volume by status). ``label_sets`` enumerates those series in order; each\nvalue set's value for this metric is a list aligned to that order.", "properties": { - "logs": { - "description": "Logs for a specific entity.", + "name": { + "description": "Canonical metric name.", + "title": "Name", + "type": "string" + }, + "unit_hint": { + "$ref": "#/components/schemas/ModelMetricUnitHintV1", + "description": "Advisory unit of the metric's values." + }, + "kind": { + "$ref": "#/components/schemas/ModelMetricKindV1", + "description": "Semantic hint for how the metric behaves (GAUGE, COUNTER, HISTOGRAM)." + }, + "label_sets": { + "description": "The metric's series, in order. Each entry is the set of labels identifying one series; the value at the same index in each value set's ``values`` is that series' value. A plain metric has a single entry with no labels (`{}`). A histogram has one entry per quantile plus an average, e.g. {'quantile': '0.5'} \u2026 {'quantile': '0.99'}, {'stat': 'avg'}. A by-status metric has one entry per status, e.g. {'status': '2xx'}.", "items": { - "$ref": "#/components/schemas/LogV1" + "additionalProperties": { + "type": "string" + }, + "type": "object" }, - "title": "Logs", + "title": "Label Sets", "type": "array" } }, "required": [ - "logs" + "name", + "unit_hint", + "kind", + "label_sets" ], - "title": "GetLogsResponseV1", + "title": "ModelMetricDescriptorV1", "type": "object" }, - "SortOrderV1": { + "ModelMetricKindV1": { + "description": "Semantic hint for how a metric behaves, to aid client rendering and\naggregation. It does not describe the value's shape (that is carried by the\ndescriptor's ``label_sets``; a metric may break down into multiple series).\n\n- ``GAUGE``: an instantaneous value (e.g. queue size, running requests).\n- ``COUNTER``: a cumulative total over the step (e.g. tokens, restarts).\n- ``HISTOGRAM``: a distribution, exposed as quantile/average series.", "enum": [ - "asc", - "desc" + "GAUGE", + "COUNTER", + "HISTOGRAM" ], - "title": "SortOrderV1", + "title": "ModelMetricKindV1", "type": "string" }, - "GetDeploymentLogsRequestV1": { - "description": "A request to fetch deployment logs.", + "ModelMetricModeV1": { + "description": "How metric values are aggregated over the request.", + "enum": [ + "CURRENT", + "SUMMARY", + "SERIES" + ], + "title": "ModelMetricModeV1", + "type": "string" + }, + "ModelMetricUnitHintV1": { + "description": "Advisory unit of a metric's values. Values are reported as scraped, so the\nhint describes the raw value (e.g. GPU memory is reported in mebibytes).\n\n- ``PER_SECOND``: a rate per second.\n- ``SECONDS``: a duration in seconds.\n- ``BYTES``: a size in bytes.\n- ``MEBIBYTES``: a size in mebibytes (MiB).\n- ``COUNT``: a dimensionless tally of discrete things.\n- ``RATIO``: a dimensionless ratio. Usually in ``[0, 1]`` but may exceed 1\n (e.g. CPU usage in cores = cpu-seconds/second).", + "enum": [ + "PER_SECOND", + "SECONDS", + "BYTES", + "MEBIBYTES", + "COUNT", + "RATIO" + ], + "title": "ModelMetricUnitHintV1", + "type": "string" + }, + "ModelMetricValueSetV1": { + "description": "The metric values for one time step. ``values`` is aligned by index to the\nresponse ``metric_descriptors`` list.", "properties": { "start_epoch_millis": { - "anyOf": [ - { - "type": "integer" + "description": "Start of the step. The step spans until the next value set's start, or the window end for the last one; a summary has a single value set starting at the window start.", + "title": "Start Epoch Millis", + "type": "integer" + }, + "values": { + "description": "Metric values aligned to the ``metric_descriptors`` index. Each entry is a list aligned to that descriptor's ``label_sets`` (a single-element list for a plain metric). A series with no data in this step is null.", + "items": { + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] }, - { - "type": "null" - } - ], - "default": null, - "description": "Epoch millis timestamp to start fetching logs", - "title": "Start Epoch Millis" + "type": "array" + }, + "title": "Values", + "type": "array" + } + }, + "required": [ + "start_epoch_millis", + "values" + ], + "title": "ModelMetricValueSetV1", + "type": "object" + }, + "GetModelMetricsResponseV1": { + "description": "Model metrics over a time window, index-mapped: metric descriptors appear once\nin ``metric_descriptors``; each value set's ``values`` are aligned to that order.", + "properties": { + "start_epoch_millis": { + "description": "Start of the returned window.", + "title": "Start Epoch Millis", + "type": "integer" }, "end_epoch_millis": { + "description": "End of the returned window.", + "title": "End Epoch Millis", + "type": "integer" + }, + "mode": { + "$ref": "#/components/schemas/ModelMetricModeV1", + "description": "The aggregation mode used." + }, + "step_seconds": { "anyOf": [ { "type": "integer" @@ -7258,39 +9795,81 @@ "type": "null" } ], - "default": null, - "description": "Epoch millis timestamp to end fetching logs", - "title": "End Epoch Millis" + "description": "Seconds per step; populated only in SERIES mode, null otherwise.", + "title": "Step Seconds" }, - "direction": { + "metric_descriptors": { + "description": "Descriptors for each metric; position defines the values index.", + "items": { + "$ref": "#/components/schemas/ModelMetricDescriptorV1" + }, + "title": "Metric Descriptors", + "type": "array" + }, + "metric_values": { + "description": "Metric values per time step covering the window. In summary mode this always contains exactly one value set spanning the whole window.", + "items": { + "$ref": "#/components/schemas/ModelMetricValueSetV1" + }, + "title": "Metric Values", + "type": "array" + } + }, + "required": [ + "start_epoch_millis", + "end_epoch_millis", + "mode", + "step_seconds", + "metric_descriptors", + "metric_values" + ], + "title": "GetModelMetricsResponseV1", + "type": "object" + }, + "GetDeploymentMetricsRequestV1": { + "description": "Query params for ``GET /v1/models/.../deployments/.../metrics``.", + "properties": { + "mode": { + "$ref": "#/components/schemas/ModelMetricModeV1", + "default": "CURRENT", + "description": "'CURRENT': a single instantaneous snapshot at now; start/end must be omitted. 'SUMMARY': a single value set aggregating the whole window. 'SERIES': evenly-spaced value sets across the window, with the step derived from the window duration." + }, + "start_epoch_millis": { "anyOf": [ { - "$ref": "#/components/schemas/SortOrderV1" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Sort order for logs" + "description": "Epoch millis timestamp to start fetching metrics. Defaults to one hour before the end.", + "title": "Start Epoch Millis" }, - "limit": { + "end_epoch_millis": { "anyOf": [ { - "maximum": 1000, - "minimum": 1, "type": "integer" }, { "type": "null" } ], - "default": 500, - "description": "Limit of logs to fetch in a single request", - "title": "Limit" + "default": null, + "description": "Epoch millis timestamp to end fetching metrics. Defaults to the current time. The window between start and end must not exceed 7 days.", + "title": "End Epoch Millis" + }, + "metrics": { + "description": "Names of the metrics to return; see https://docs.baseten.co/observability/export-metrics/supported-metrics for the available names. When omitted, a default set is returned: baseten_replicas_active, baseten_inference_requests_total, and baseten_end_to_end_response_time_seconds. Unknown names are rejected; valid names that do not apply are omitted from the response.", + "items": { + "type": "string" + }, + "title": "Metrics", + "type": "array" } }, - "title": "GetDeploymentLogsRequestV1", + "title": "GetDeploymentMetricsRequestV1", "type": "object" }, "TerminateReplicaResponseV1": { @@ -7626,10 +10205,10 @@ ] }, "max_surge_percent": { - "default": 10, + "default": 25, "description": "The maximum surge percentage for rolling deploys.", "examples": [ - 10 + 25 ], "title": "Max Surge Percent", "type": "integer" @@ -7815,10 +10394,10 @@ "type": "null" } ], - "default": 10, + "default": null, "description": "The maximum surge percentage for rolling deploys.", "examples": [ - 10 + 25 ], "title": "Max Surge Percent" }, @@ -7992,6 +10571,198 @@ "title": "UpdateEnvironmentRequestV1", "type": "object" }, + "GetEnvironmentLogsRequestV1": { + "description": "A request to fetch logs for a model environment.\n\nReturns logs from every deployment that was active on the environment over\nthe requested time range, merged in timestamp order.", + "properties": { + "start_epoch_millis": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + "title": "Start Epoch Millis" + }, + "end_epoch_millis": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + "title": "End Epoch Millis" + }, + "direction": { + "anyOf": [ + { + "$ref": "#/components/schemas/SortOrderV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sort order for logs" + }, + "limit": { + "anyOf": [ + { + "maximum": 1000, + "minimum": 1, + "type": "integer" + }, + { + "type": "null" + } + ], + "default": 500, + "description": "Limit of logs to fetch in a single request", + "title": "Limit" + }, + "min_level": { + "anyOf": [ + { + "$ref": "#/components/schemas/LogLevelV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." + }, + "replica": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Only return logs emitted by this replica (5-char short ID).", + "title": "Replica" + }, + "request_id": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Only return logs tagged with this inference request ID.", + "title": "Request Id" + }, + "component": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Only return logs from this component.", + "title": "Component" + }, + "search_pattern": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", + "title": "Search Pattern" + }, + "includes": { + "description": "Case-sensitive substrings that must all appear in the log message.", + "items": { + "type": "string" + }, + "maxItems": 8, + "title": "Includes", + "type": "array" + }, + "excludes": { + "description": "Case-sensitive substrings; lines containing any of these are dropped.", + "items": { + "type": "string" + }, + "maxItems": 8, + "title": "Excludes", + "type": "array" + } + }, + "title": "GetEnvironmentLogsRequestV1", + "type": "object" + }, + "GetEnvironmentMetricsRequestV1": { + "description": "Query params for ``GET /v1/models/.../environments/.../metrics``.", + "properties": { + "mode": { + "$ref": "#/components/schemas/ModelMetricModeV1", + "default": "CURRENT", + "description": "'CURRENT': a single instantaneous snapshot at now; start/end must be omitted. 'SUMMARY': a single value set aggregating the whole window. 'SERIES': evenly-spaced value sets across the window, with the step derived from the window duration." + }, + "start_epoch_millis": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Epoch millis timestamp to start fetching metrics. Defaults to one hour before the end.", + "title": "Start Epoch Millis" + }, + "end_epoch_millis": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Epoch millis timestamp to end fetching metrics. Defaults to the current time. The window between start and end must not exceed 7 days.", + "title": "End Epoch Millis" + }, + "metrics": { + "description": "Names of the metrics to return; see https://docs.baseten.co/observability/export-metrics/supported-metrics for the available names. When omitted, a default set is returned: baseten_replicas_active, baseten_inference_requests_total, and baseten_end_to_end_response_time_seconds. Unknown names are rejected; valid names that do not apply are omitted from the response.", + "items": { + "type": "string" + }, + "title": "Metrics", + "type": "array" + } + }, + "title": "GetEnvironmentMetricsRequestV1", + "type": "object" + }, "PromoteToEnvironmentRequestV1": { "description": "A request to promote a deployment to a environment.", "properties": { @@ -8923,6 +11694,11 @@ "title": "Priority", "type": "integer" }, + "availability_model": { + "$ref": "#/components/schemas/V1AvailabilityModel", + "default": "dedicated", + "description": "Capacity guarantee for the job. 'dedicated' is non-preemptible on-demand capacity; 'spot' is interruptible." + }, "user": { "anyOf": [ { @@ -9048,6 +11824,15 @@ "title": "UserV1", "type": "object" }, + "V1AvailabilityModel": { + "description": "Capacity guarantee under which a training job is scheduled.\n\n``DEDICATED`` is on-demand capacity that is not preempted (the default). ``SPOT`` is\ninterruptible capacity that may be preempted; the user is responsible for checkpointing\ntheir own progress. A managed/resumable model where the platform handles\ncheckpoint/resume on its own is intentionally not defined yet; it is planned for a\nfuture milestone.", + "enum": [ + "dedicated", + "spot" + ], + "title": "V1AvailabilityModel", + "type": "string" + }, "UpsertTrainingProjectResponseV1": { "description": "A response to upserting a training project.", "properties": { @@ -9228,15 +12013,16 @@ "type": "object" }, "CreateJobWeightConfigV1": { - "description": "Weight source configuration for MDN (Model Distribution Network).\n\nEnables training jobs to mount external model weights from HuggingFace, S3, GCS, or R2\nvia MDN's caching and CSI mounting infrastructure. Weights are mirrored once and\ndeduplicated across training jobs.", + "description": "Weight source configuration for MDN (Model Distribution Network).\n\nEnables training jobs to mount external model weights from HuggingFace, S3, GCS, R2,\nor CoreWeave via MDN's caching and CSI mounting infrastructure. Weights are mirrored\nonce and deduplicated across training jobs.", "properties": { "source": { - "description": "Weight source URI. Supported formats: hf://, s3://, gs://, r2://", + "description": "Weight source URI. Supported formats: hf://, s3://, gs://, r2://, cw://", "examples": [ "hf://meta-llama/Llama-3-8B@main", "s3://my-bucket/models/llama", "gs://my-bucket/models/llama", - "r2://account_id.bucket/models/llama" + "r2://account_id.bucket/models/llama", + "cw://my-bucket/models/llama" ], "title": "Source", "type": "string" @@ -9503,6 +12289,14 @@ "count": 2 } ] + }, + "availability_model": { + "$ref": "#/components/schemas/V1AvailabilityModel", + "default": "dedicated", + "description": "Capacity guarantee for the job. 'dedicated' (the default) runs on on-demand capacity that is not preempted. 'spot' runs on interruptible capacity that may be preempted; the user is responsible for checkpointing their own progress.", + "examples": [ + "spot" + ] } }, "title": "CreateTrainingJobComputeV1", @@ -9692,6 +12486,7 @@ "accelerator": "H100", "count": 2 }, + "availability_model": "spot", "cpu_count": 1, "memory": "2Gi", "node_count": 1 @@ -10045,7 +12840,8 @@ "discriminator": { "mapping": { "baseten_latest_checkpoint": "#/components/schemas/BasetenLatestCheckpointConfig", - "baseten_named_checkpoint": "#/components/schemas/BasetenNamedCheckpointConfig" + "baseten_named_checkpoint": "#/components/schemas/BasetenNamedCheckpointConfig", + "loops_checkpoint": "#/components/schemas/LoopsCheckpointConfig" }, "propertyName": "typ" }, @@ -10055,6 +12851,9 @@ }, { "$ref": "#/components/schemas/BasetenNamedCheckpointConfig" + }, + { + "$ref": "#/components/schemas/LoopsCheckpointConfig" } ] }, @@ -10065,6 +12864,42 @@ "title": "LoadCheckpointConfig", "type": "object" }, + "LoopsCheckpointConfig": { + "properties": { + "run_id": { + "description": "ID of the Loops run to load the checkpoint from", + "title": "Run Id", + "type": "string" + }, + "checkpoint_name": { + "description": "Name of the checkpoint to load", + "title": "Checkpoint Name", + "type": "string" + }, + "target": { + "default": "trainer", + "description": "Which checkpoint target to load: 'trainer' (full training state) or 'sampler' (inference weights)", + "enum": [ + "trainer", + "sampler" + ], + "title": "Target", + "type": "string" + }, + "typ": { + "const": "loops_checkpoint", + "default": "loops_checkpoint", + "title": "Typ", + "type": "string" + } + }, + "required": [ + "run_id", + "checkpoint_name" + ], + "title": "LoopsCheckpointConfig", + "type": "object" + }, "RegistrySecretDockerAuthV1": { "description": "Authentication via a Baseten secret for any Docker registry (Docker Hub, GHCR, NGC, etc.).\nThe referenced secret must contain credentials in the format 'username:password'.\nFor Docker Hub, set registry to 'https://index.docker.io/v1/'. For GHCR, use 'ghcr.io'.", "properties": { @@ -10272,11 +13107,45 @@ "title": "GetTrainingJobResponseV1", "type": "object" }, + "UpdateTrainingJobRequestV1": { + "description": "A request to update mutable fields on a training job.", + "properties": { + "priority": { + "description": "New queue priority for a PENDING training job. Higher values are dequeued first. Only jobs in the PENDING state can have their priority changed.", + "examples": [ + 0, + 10, + 100 + ], + "title": "Priority", + "type": "integer" + } + }, + "required": [ + "priority" + ], + "title": "UpdateTrainingJobRequestV1", + "type": "object" + }, + "UpdateTrainingJobResponseV1": { + "description": "A response to updating a training job.", + "properties": { + "training_job": { + "$ref": "#/components/schemas/TrainingJobV1", + "description": "The updated training job." + } + }, + "required": [ + "training_job" + ], + "title": "UpdateTrainingJobResponseV1", + "type": "object" + }, "DownloadTrainingJobResponseV1": { - "description": "A response that includes the artifacts for a training job", + "description": "A response with presigned URLs for a training job's artifacts.", "properties": { "artifact_presigned_urls": { - "description": "Presigned URL's for the artifacts", + "description": "Presigned URLs for the job's uploaded artifacts.", "items": { "type": "string" }, @@ -10317,7 +13186,7 @@ } ], "default": null, - "description": "Epoch millis timestamp to start fetching logs", + "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", "title": "Start Epoch Millis" }, "end_epoch_millis": { @@ -10330,7 +13199,7 @@ } ], "default": null, - "description": "Epoch millis timestamp to end fetching logs", + "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", "title": "End Epoch Millis" }, "direction": { @@ -10359,6 +13228,18 @@ "default": 500, "description": "Limit of logs to fetch in a single request", "title": "Limit" + }, + "min_level": { + "anyOf": [ + { + "$ref": "#/components/schemas/LogLevelV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." } }, "title": "GetTrainingJobLogsRequestV1", @@ -10586,7 +13467,20 @@ "description": "Epoch millis timestamp to end fetching metrics", "title": "End Epoch Millis" }, - "start_epoch_millis": { + "start_epoch_millis": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Epoch millis timestamp to start fetching metrics.", + "title": "Start Epoch Millis" + }, + "step_seconds": { "anyOf": [ { "type": "integer" @@ -10596,8 +13490,8 @@ } ], "default": null, - "description": "Epoch millis timestamp to start fetching metrics.", - "title": "Start Epoch Millis" + "description": "Resolution of the returned series, in seconds. When omitted, a step is derived from the time range so large windows return fewer points.", + "title": "Step Seconds" } }, "title": "GetTrainingJobMetricsRequestV1", @@ -11338,350 +14232,155 @@ "title": "SearchTrainingJobsResponseV1", "type": "object" }, - "SearchTrainersRequestV1": { - "description": "Filters for searching trainers visible to the requesting user.", - "properties": { - "trainer_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Filter by trainer ID.", - "examples": [ - "k4q95w5" - ], - "title": "Trainer Id" - } - }, - "title": "SearchTrainersRequestV1", - "type": "object" - }, - "SearchedTrainerV1": { - "description": "Trainer entry returned by /v1/trainers/search.", + "SupportedModelV1": { + "description": "A model supported by the Loops server.", "properties": { - "trainer_id": { - "description": "The trainer ID.", - "title": "Trainer Id", - "type": "string" - }, - "session_id": { - "description": "The session ID this trainer belongs to.", - "title": "Session Id", + "model_name": { + "description": "The name of the supported model.", + "title": "Model Name", "type": "string" }, - "base_model": { - "description": "The HuggingFace base model the trainer is fine-tuning.", - "title": "Base Model", - "type": "string" + "max_context_length": { + "description": "The maximum context length (in tokens) supported by this model.", + "title": "Max Context Length", + "type": "integer" } }, "required": [ - "trainer_id", - "session_id", - "base_model" + "model_name", + "max_context_length" ], - "title": "SearchedTrainerV1", + "title": "SupportedModelV1", "type": "object" }, - "SearchTrainersResponseV1": { - "description": "Trainers matching the search filters.", + "GetLoopsCapabilitiesResponseV1": { + "description": "Response for ``GET /v1/loops/capabilities``.", "properties": { - "trainers": { - "description": "List of trainers.", + "supported_models": { + "description": "List of models available on the server.", "items": { - "$ref": "#/components/schemas/SearchedTrainerV1" + "$ref": "#/components/schemas/SupportedModelV1" }, - "title": "Trainers", + "title": "Supported Models", "type": "array" } }, - "required": [ - "trainers" - ], - "title": "SearchTrainersResponseV1", - "type": "object" - }, - "CheckpointSearchRequestV1": { - "description": "Lookup body for ``POST /v1/trainers/checkpoints/search``.", - "properties": { - "checkpoint_path": { - "description": "bt:// URI of a trainer checkpoint. Form: bt://loops:/(weights|sampler_weights)/.", - "examples": [ - "bt://loops:k4q95w5/sampler_weights/step-100" - ], - "title": "Checkpoint Path", - "type": "string" - } - }, - "required": [ - "checkpoint_path" - ], - "title": "CheckpointSearchRequestV1", - "type": "object" - }, - "TrainerCheckpointTarget": { - "description": "Whether a TrainerServerCheckpoint is loadable by the sampler or the trainer.\n\nSAMPLER checkpoints are consumed by the sampling server for inference;\nTRAINER checkpoints capture full trainer state for resuming training.\nMirrored in the bt:// URI as\n``bt://loops:/(sampler_weights|weights)/``.", - "enum": [ - "sampler", - "trainer" - ], - "title": "TrainerCheckpointTarget", - "type": "string" - }, - "TrainerServerCheckpointV1": { - "description": "A checkpoint saved by a trainer.", - "properties": { - "checkpoint_id": { - "description": "The ID of the checkpoint.", - "title": "Checkpoint Id", - "type": "string" - }, - "created_at": { - "description": "The timestamp of the checkpoint in ISO 8601 format.", - "format": "date-time", - "title": "Created At", - "type": "string" - }, - "checkpoint_type": { - "description": "The type of checkpoint.", - "title": "Checkpoint Type", - "type": "string" - }, - "base_model": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The base model of the checkpoint.", - "title": "Base Model" - }, - "lora_adapter_config": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The adapter config of the checkpoint.", - "title": "Lora Adapter Config" - }, - "size_bytes": { - "description": "The size of the checkpoint in bytes.", - "title": "Size Bytes", - "type": "integer" - }, - "sync_status": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Sync state of the checkpoint: SYNCING or COMPLETE.", - "title": "Sync Status" - }, - "id": { - "description": "The TrainerServerCheckpoint database ID.", - "title": "Id", - "type": "string" - }, - "trainer_id": { - "description": "The ID of the trainer.", - "title": "Trainer Id", - "type": "string" - }, - "target": { - "$ref": "#/components/schemas/TrainerCheckpointTarget", - "description": "Whether this checkpoint is loadable by the sampler ('sampler') or by the trainer ('trainer')." - } - }, - "required": [ - "checkpoint_id", - "created_at", - "checkpoint_type", - "base_model", - "lora_adapter_config", - "size_bytes", - "id", - "trainer_id", - "target" - ], - "title": "TrainerServerCheckpointV1", - "type": "object" - }, - "CheckpointSearchResponseV1": { - "description": "Response for ``POST /v1/trainers/checkpoints/search``.", - "properties": { - "checkpoint": { - "$ref": "#/components/schemas/TrainerServerCheckpointV1", - "description": "The checkpoint metadata (id, target, type, sizes, etc.)." - } - }, - "required": [ - "checkpoint" - ], - "title": "CheckpointSearchResponseV1", - "type": "object" - }, - "CreateTrainerSessionRequestV1": { - "properties": { - "training_project_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "ID of the training project to associate with. If omitted, a default project is created for the org.", - "title": "Training Project Id" - } - }, - "title": "CreateTrainerSessionRequestV1", - "type": "object" - }, - "TrainerSessionV1": { - "properties": { - "id": { - "title": "Id", - "type": "string" - } - }, - "required": [ - "id" - ], - "title": "TrainerSessionV1", - "type": "object" - }, - "CreateTrainerSessionResponseV1": { - "properties": { - "session": { - "$ref": "#/components/schemas/TrainerSessionV1" - } - }, - "required": [ - "session" - ], - "title": "CreateTrainerSessionResponseV1", - "type": "object" - }, - "CreateTrainerServerRequestV1": { - "properties": { - "model": { - "description": "Base model ID (e.g. 'Qwen/Qwen3-8B').", - "title": "Model", - "type": "string" - }, - "max_seq_len": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Maximum sequence length for training. Defaults to the maximum supported by the model configuration.", - "title": "Max Seq Len" - }, - "lora_rank": { - "default": 64, - "description": "LoRA rank.", - "title": "Lora Rank", - "type": "integer" - }, - "seed": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Random seed for reproducibility.", - "title": "Seed" - }, - "scale_down_delay_seconds": { - "default": 3600, - "description": "Seconds of inactivity before the trainer scales to zero. Must be positive. Defaults to 3600 (1 hour).", - "exclusiveMinimum": 0, - "title": "Scale Down Delay Seconds", - "type": "integer" - }, - "checkpoint_path": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Optional bt:// URI of an existing trainer-target checkpoint to resume training from. Form: bt://loops:/weights/.", - "examples": [ - "bt://loops:k4q95w5/weights/step-100" - ], - "title": "Checkpoint Path" + "required": [ + "supported_models" + ], + "title": "GetLoopsCapabilitiesResponseV1", + "type": "object" + }, + "LoopsSessionV1": { + "properties": { + "id": { + "title": "Id", + "type": "string" + } + }, + "required": [ + "id" + ], + "title": "LoopsSessionV1", + "type": "object" + }, + "CreateLoopsSessionResponseV1": { + "properties": { + "session": { + "$ref": "#/components/schemas/LoopsSessionV1" + } + }, + "required": [ + "session" + ], + "title": "CreateLoopsSessionResponseV1", + "type": "object" + }, + "GetLoopsSessionResponseV1": { + "description": "Response for ``GET /v1/loops/sessions/``.", + "properties": { + "session": { + "$ref": "#/components/schemas/LoopsSessionV1", + "description": "The Loops session." } }, "required": [ - "model" + "session" ], - "title": "CreateTrainerServerRequestV1", + "title": "GetLoopsSessionResponseV1", "type": "object" }, - "SamplingServerV1": { + "LoopsRunV1": { "properties": { "id": { + "description": "The run ID.", "title": "Id", "type": "string" }, + "session_id": { + "description": "The session ID this run belongs to.", + "title": "Session Id", + "type": "string" + }, + "deployment_id": { + "description": "The ID of the Loops deployment the run executes on.", + "title": "Deployment Id", + "type": "string" + }, + "name": { + "description": "The run's display name.", + "title": "Name", + "type": "string" + }, + "base_model": { + "description": "The HuggingFace base model the run is fine-tuning.", + "title": "Base Model", + "type": "string" + }, "base_url": { + "description": "The run's base URL.", "title": "Base Url", "type": "string" }, - "model_id": { - "description": "Hashid of the underlying Baseten model.", - "title": "Model Id", + "created_at": { + "description": "Time the run was created in ISO 8601 format", + "format": "date-time", + "title": "Created At", "type": "string" }, - "deployment_id": { - "description": "Hashid of the specific model deployment (version).", - "title": "Deployment Id", - "type": "string" + "sampler": { + "$ref": "#/components/schemas/LoopsSamplerV1", + "description": "The sampler bound to this run." } }, "required": [ "id", + "session_id", + "deployment_id", + "name", + "base_model", "base_url", - "model_id", - "deployment_id" + "created_at", + "sampler" + ], + "title": "LoopsRunV1", + "type": "object" + }, + "LoopsSamplerStatusV1": { + "description": "The current status of a Loops sampler.", + "properties": { + "name": { + "$ref": "#/components/schemas/DeploymentStatusV1", + "description": "The current status of the Loops sampler." + } + }, + "required": [ + "name" ], - "title": "SamplingServerV1", + "title": "LoopsSamplerStatusV1", "type": "object" }, - "TrainerServerV1": { + "LoopsSamplerV1": { "properties": { "id": { "title": "Id", @@ -11691,51 +14390,82 @@ "title": "Base Url", "type": "string" }, - "sampling_server": { - "$ref": "#/components/schemas/SamplingServerV1" + "base_model": { + "description": "The HuggingFace base model the sampler is serving.", + "title": "Base Model", + "type": "string" + }, + "created_at": { + "description": "Time the sampler was created in ISO 8601 format", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "model_id": { + "description": "Hashid of the underlying Baseten model.", + "title": "Model Id", + "type": "string" + }, + "deployment_id": { + "description": "Hashid of the specific model deployment (version).", + "title": "Deployment Id", + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/LoopsSamplerStatusV1", + "description": "The sampler's current status." } }, "required": [ "id", "base_url", - "sampling_server" + "base_model", + "created_at", + "model_id", + "deployment_id", + "status" ], - "title": "TrainerServerV1", + "title": "LoopsSamplerV1", "type": "object" }, - "CreateTrainerServerResponseV1": { + "ListLoopsRunsResponseV1": { + "description": "Runs matching the query filters.", "properties": { - "trainer_server": { - "$ref": "#/components/schemas/TrainerServerV1" + "runs": { + "description": "List of runs.", + "items": { + "$ref": "#/components/schemas/LoopsRunV1" + }, + "title": "Runs", + "type": "array" } }, "required": [ - "trainer_server" + "runs" ], - "title": "CreateTrainerServerResponseV1", + "title": "ListLoopsRunsResponseV1", "type": "object" }, - "CreateSamplingServerRequestV1": { + "ListLoopsRunsQueryParamsV1": { + "description": "Query-string filters for ``GET /v1/loops/runs``.\n\nBoth filters are optional and can be combined; omit both to list all\nruns visible to the caller.", "properties": { - "model": { - "description": "Model to use for standalone samplers (eg, for baselines).", - "title": "Model", - "type": "string" - }, - "max_seq_length": { + "run_id": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Maximum prompt length (in tokens) the sampler must handle. Set this to the longest prompt you plan to send. Omit to use the default for the base model.", - "title": "Max Seq Length" + "description": "Filter by run ID.", + "examples": [ + "k4q95w5" + ], + "title": "Run Id" }, - "checkpoint_path": { + "base_model": { "anyOf": [ { "type": "string" @@ -11745,134 +14475,107 @@ } ], "default": null, - "description": "Optional bt:// URI of an existing sampler-target checkpoint to load weights from on startup. Form: bt://loops:/sampler_weights/.", + "description": "Filter runs by base model name.", "examples": [ - "bt://loops:k4q95w5/sampler_weights/step-100" + "Qwen/Qwen3-8B" ], - "title": "Checkpoint Path" - } - }, - "required": [ - "model" - ], - "title": "CreateSamplingServerRequestV1", - "type": "object" - }, - "CreateSamplingServerResponseV1": { - "properties": { - "sampling_server": { - "$ref": "#/components/schemas/SamplingServerV1" + "title": "Base Model" } }, - "required": [ - "sampling_server" - ], - "title": "CreateSamplingServerResponseV1", + "title": "ListLoopsRunsQueryParamsV1", "type": "object" }, - "GetTrainerServerCheckpointsResponseV1": { - "description": "A response to list checkpoints for a trainer.", + "CreateLoopsRunRequestV1": { "properties": { - "trainer_id": { - "description": "The ID of the trainer.", - "title": "Trainer Id", + "session_id": { + "description": "ID of the Loops session this run belongs to.", + "title": "Session Id", "type": "string" }, - "checkpoints": { - "description": "The checkpoints for the trainer.", - "items": { - "$ref": "#/components/schemas/TrainerServerCheckpointV1" - }, - "title": "Checkpoints", - "type": "array" - } - }, - "required": [ - "trainer_id", - "checkpoints" - ], - "title": "GetTrainerServerCheckpointsResponseV1", - "type": "object" - }, - "GetTrainerServerCheckpointFilesResponseV1": { - "description": "A response to fetch presigned URLs for files under a trainer server checkpoint.", - "properties": { - "presigned_urls": { - "description": "List of presigned URLs for checkpoint files.", - "items": { - "$ref": "#/components/schemas/CheckpointFile" - }, - "title": "Presigned Urls", - "type": "array" + "base_model": { + "description": "Base model ID (e.g. 'Qwen/Qwen3-8B').", + "title": "Base Model", + "type": "string" + }, + "name": { + "anyOf": [ + { + "maxLength": 255, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional display name for the run. Defaults to the base model name when omitted.", + "title": "Name" + }, + "max_seq_len": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Maximum prompt length (in tokens) the run must handle. Set this to the longest training example you plan to send. Defaults to the maximum supported by the model configuration.", + "title": "Max Seq Len" + }, + "lora_rank": { + "default": 64, + "description": "LoRA rank.", + "title": "Lora Rank", + "type": "integer" + }, + "seed": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Random seed for reproducibility.", + "title": "Seed" + }, + "scale_down_delay_seconds": { + "default": 3600, + "description": "Seconds of inactivity before the run scales to zero. Must be between 1 and 3600 (1 hour). Defaults to 3600.", + "exclusiveMinimum": 0, + "maximum": 3600, + "title": "Scale Down Delay Seconds", + "type": "integer" + }, + "replicas": { + "default": 1, + "description": "Number of data-parallel trainer replicas. Each replica is one full copy of the model's preset node group, so the trainer deployment runs (preset node_count * replicas) nodes (e.g. replicas=4 on a 4-node preset \u2192 16 nodes, 4 DP workers). Must be a positive integer. Defaults to 1.", + "minimum": 1, + "title": "Replicas", + "type": "integer" }, - "next_page_token": { + "path": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Token to use for fetching the next page of results. None when there are no more results.", - "title": "Next Page Token" - }, - "total_count": { - "description": "Total number of checkpoint files available.", - "title": "Total Count", - "type": "integer" - } - }, - "required": [ - "presigned_urls", - "total_count" - ], - "title": "GetTrainerServerCheckpointFilesResponseV1", - "type": "object" - }, - "SupportedModelV1": { - "description": "A model supported by the Loops server.", - "properties": { - "model_name": { - "description": "The name of the supported model.", - "title": "Model Name", - "type": "string" + "description": "Optional bt:// URI of an existing checkpoint to load weights from on startup. Form: bt://loops:/weights/.", + "examples": [ + "bt://loops:k4q95w5/weights/step-100" + ], + "title": "Path" }, - "max_context_length": { - "description": "The maximum context length (in tokens) supported by this model.", - "title": "Max Context Length", - "type": "integer" - } - }, - "required": [ - "model_name", - "max_context_length" - ], - "title": "SupportedModelV1", - "type": "object" - }, - "GetLoopsCapabilitiesResponseV1": { - "description": "Response for ``GET /v1/loops/capabilities``.", - "properties": { - "supported_models": { - "description": "List of models available on the server.", - "items": { - "$ref": "#/components/schemas/SupportedModelV1" - }, - "title": "Supported Models", - "type": "array" - } - }, - "required": [ - "supported_models" - ], - "title": "GetLoopsCapabilitiesResponseV1", - "type": "object" - }, - "CreateLoopsSessionRequestV1": { - "properties": { - "training_project_id": { + "reuse_from_session_id": { "anyOf": [ { "type": "string" @@ -11882,178 +14585,269 @@ } ], "default": null, - "description": "ID of the training project to associate with. If omitted, a default project is created for the org.", - "title": "Training Project Id" + "description": "Optional Loops session ID whose trainer deployment should be reused for this run, sharing the infrastructure across sessions instead of provisioning fresh. The named session must belong to the same team. Reuse is best-effort: if the prior deployment is stopped, failed, its sampler is unhealthy, or this run requests replicas != 1, a new deployment is provisioned instead.", + "title": "Reuse From Session Id" } }, - "title": "CreateLoopsSessionRequestV1", + "required": [ + "session_id", + "base_model" + ], + "title": "CreateLoopsRunRequestV1", "type": "object" }, - "LoopsSessionV1": { + "CreateLoopsRunResponseV1": { "properties": { - "id": { - "title": "Id", - "type": "string" + "run": { + "$ref": "#/components/schemas/LoopsRunV1" } }, "required": [ - "id" + "run" ], - "title": "LoopsSessionV1", + "title": "CreateLoopsRunResponseV1", "type": "object" }, - "CreateLoopsSessionResponseV1": { + "GetLoopsRunResponseV1": { + "description": "Response for ``GET /v1/loops/runs/``.", "properties": { - "session": { - "$ref": "#/components/schemas/LoopsSessionV1" + "run": { + "$ref": "#/components/schemas/LoopsRunV1", + "description": "The Loops run with its associated sampler." } }, "required": [ - "session" + "run" ], - "title": "CreateLoopsSessionResponseV1", + "title": "GetLoopsRunResponseV1", "type": "object" }, - "GetLoopsSessionResponseV1": { - "description": "Response for ``GET /v1/loops/sessions/``.", + "ListLoopsSamplersResponseV1": { + "description": "Response for ``GET /v1/loops/samplers``.\n\nReturns the caller's samplers, including those paired to runs and\nstandalone samplers. Ordered newest-first.", "properties": { - "session": { - "$ref": "#/components/schemas/LoopsSessionV1", - "description": "The Loops session." + "samplers": { + "description": "List of samplers.", + "items": { + "$ref": "#/components/schemas/LoopsSamplerV1" + }, + "title": "Samplers", + "type": "array" } }, "required": [ - "session" + "samplers" ], - "title": "GetLoopsSessionResponseV1", + "title": "ListLoopsSamplersResponseV1", "type": "object" }, - "LoopsRunV1": { + "CreateLoopsSamplerRequestV1": { "properties": { - "id": { - "description": "The run ID.", - "title": "Id", - "type": "string" - }, "session_id": { - "description": "The session ID this run belongs to.", + "description": "ID of the Loops session this sampler belongs to.", "title": "Session Id", "type": "string" }, "base_model": { - "description": "The HuggingFace base model the run is fine-tuning.", + "description": "Base model ID for standalone samplers (e.g., for baselines).", "title": "Base Model", "type": "string" }, - "base_url": { - "description": "The run's base URL.", - "title": "Base Url", - "type": "string" + "max_seq_length": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Maximum prompt length (in tokens) the sampler must handle. Set this to the longest prompt you plan to send. Omit to use the default for the base model.", + "title": "Max Seq Length" }, - "created_at": { - "description": "Time the run was created in ISO 8601 format", - "format": "date-time", - "title": "Created At", - "type": "string" + "model_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional bt:// URI of an existing sampler-target checkpoint to load weights from on startup. Form: bt://loops:/sampler_weights/.", + "examples": [ + "bt://loops:k4q95w5/sampler_weights/step-100" + ], + "title": "Model Path" }, - "sampler": { - "$ref": "#/components/schemas/LoopsSamplerV1", - "description": "The sampler bound to this run." + "reuse_from_session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional Loops session ID whose deployment should be reused for this sampler. Same best-effort semantics as the run endpoint.", + "title": "Reuse From Session Id" } }, "required": [ - "id", "session_id", - "base_model", - "base_url", - "created_at", + "base_model" + ], + "title": "CreateLoopsSamplerRequestV1", + "type": "object" + }, + "CreateLoopsSamplerResponseV1": { + "properties": { + "sampler": { + "$ref": "#/components/schemas/LoopsSamplerV1" + } + }, + "required": [ "sampler" ], - "title": "LoopsRunV1", + "title": "CreateLoopsSamplerResponseV1", "type": "object" }, - "LoopsSamplerStatusV1": { - "description": "The current status of a Loops sampler.", + "GetLoopsSamplerResponseV1": { + "description": "Response for ``GET /v1/loops/samplers/``.", "properties": { - "name": { - "$ref": "#/components/schemas/DeploymentStatusV1", - "description": "The current status of the Loops sampler." + "sampler": { + "$ref": "#/components/schemas/LoopsSamplerV1", + "description": "The Loops sampler." } }, "required": [ - "name" + "sampler" ], - "title": "LoopsSamplerStatusV1", + "title": "GetLoopsSamplerResponseV1", "type": "object" }, - "LoopsSamplerV1": { + "LoopsCheckpointV1": { + "description": "A checkpoint saved by a Loops run.", "properties": { - "id": { - "title": "Id", + "checkpoint_id": { + "description": "The ID of the checkpoint.", + "title": "Checkpoint Id", "type": "string" }, - "base_url": { - "title": "Base Url", + "created_at": { + "description": "The timestamp of the checkpoint in ISO 8601 format.", + "format": "date-time", + "title": "Created At", "type": "string" }, - "base_model": { - "description": "The HuggingFace base model the sampler is serving.", - "title": "Base Model", + "checkpoint_type": { + "description": "The type of checkpoint.", + "title": "Checkpoint Type", "type": "string" }, - "created_at": { - "description": "Time the sampler was created in ISO 8601 format", - "format": "date-time", - "title": "Created At", - "type": "string" + "base_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The base model of the checkpoint.", + "title": "Base Model" + }, + "lora_adapter_config": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The adapter config of the checkpoint.", + "title": "Lora Adapter Config" + }, + "size_bytes": { + "description": "The size of the checkpoint in bytes.", + "title": "Size Bytes", + "type": "integer" + }, + "sync_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sync state of the checkpoint: SYNCING or COMPLETE.", + "title": "Sync Status" }, - "model_id": { - "description": "Hashid of the underlying Baseten model.", - "title": "Model Id", + "id": { + "description": "The checkpoint ID.", + "title": "Id", "type": "string" }, - "deployment_id": { - "description": "Hashid of the specific model deployment (version).", - "title": "Deployment Id", + "run_id": { + "description": "The ID of the run that produced the checkpoint.", + "title": "Run Id", "type": "string" }, - "status": { - "$ref": "#/components/schemas/LoopsSamplerStatusV1", - "description": "The sampler's current status." + "target": { + "$ref": "#/components/schemas/TrainerCheckpointTarget", + "description": "Whether this checkpoint is loadable by the sampler or by the run." } }, "required": [ - "id", - "base_url", - "base_model", + "checkpoint_id", "created_at", - "model_id", - "deployment_id", - "status" + "checkpoint_type", + "base_model", + "lora_adapter_config", + "size_bytes", + "id", + "run_id", + "target" ], - "title": "LoopsSamplerV1", + "title": "LoopsCheckpointV1", "type": "object" }, - "ListLoopsRunsResponseV1": { - "description": "Runs matching the query filters.", + "TrainerCheckpointTarget": { + "description": "Whether a TrainerServerCheckpoint is loadable by the sampler or the trainer.\n\nSAMPLER checkpoints are consumed by the sampling server for inference;\nTRAINER checkpoints capture full trainer state for resuming training.\nMirrored in the bt:// URI as\n``bt://loops:/(sampler_weights|weights)/``.", + "enum": [ + "sampler", + "trainer" + ], + "title": "TrainerCheckpointTarget", + "type": "string" + }, + "ListLoopsCheckpointsResponseV1": { + "description": "Checkpoints matching the query filter.", "properties": { - "runs": { - "description": "List of runs.", + "checkpoints": { + "description": "Matching checkpoints.", "items": { - "$ref": "#/components/schemas/LoopsRunV1" + "$ref": "#/components/schemas/LoopsCheckpointV1" }, - "title": "Runs", + "title": "Checkpoints", "type": "array" } }, "required": [ - "runs" + "checkpoints" ], - "title": "ListLoopsRunsResponseV1", + "title": "ListLoopsCheckpointsResponseV1", "type": "object" }, - "ListLoopsRunsQueryParamsV1": { - "description": "Query-string filters for ``GET /v1/loops/runs``.\n\nBoth filters are optional and can be combined; omit both to list all\nruns visible to the caller.", + "ListLoopsCheckpointsQueryParamsV1": { + "description": "Query-string filters for ``GET /v1/loops/checkpoints``.\n\nProvide exactly one of ``run_id`` (all checkpoints for the run),\n``base_model`` (all checkpoints across the caller's runs of that\nbase model), or ``checkpoint_path`` (the single matching checkpoint).", "properties": { "run_id": { "anyOf": [ @@ -12065,7 +14859,7 @@ } ], "default": null, - "description": "Filter by run ID.", + "description": "Filter by run ID. Returns all checkpoints saved by the run.", "examples": [ "k4q95w5" ], @@ -12081,48 +14875,68 @@ } ], "default": null, - "description": "Filter runs by base model name.", + "description": "Filter by base model. Returns checkpoints across the caller's runs of this base model.", "examples": [ "Qwen/Qwen3-8B" ], "title": "Base Model" - } - }, - "title": "ListLoopsRunsQueryParamsV1", - "type": "object" - }, - "CreateLoopsRunRequestV1": { - "properties": { - "session_id": { - "description": "ID of the Loops session this run belongs to.", - "title": "Session Id", - "type": "string" - }, - "base_model": { - "description": "Base model ID (e.g. 'Qwen/Qwen3-8B').", - "title": "Base Model", - "type": "string" }, - "max_seq_len": { + "checkpoint_path": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Maximum prompt length (in tokens) the run must handle. Set this to the longest training example you plan to send. Defaults to the maximum supported by the model configuration.", - "title": "Max Seq Len" - }, - "lora_rank": { - "default": 64, - "description": "LoRA rank.", - "title": "Lora Rank", - "type": "integer" + "description": "bt:// URI of a Loops checkpoint. Form: bt://loops:/(weights|sampler_weights)/.", + "examples": [ + "bt://loops:k4q95w5/sampler_weights/step-100" + ], + "title": "Checkpoint Path" + } + }, + "title": "ListLoopsCheckpointsQueryParamsV1", + "type": "object" + }, + "ValidateLoopsCheckpointRequestV1": { + "description": "Request body for ``POST /v1/loops/checkpoints/validate``.", + "properties": { + "checkpoint_path": { + "description": "bt:// URI of a sampler checkpoint. Form: bt://loops:/sampler_weights/.", + "examples": [ + "bt://loops:k4q95w5/sampler_weights/step-100" + ], + "title": "Checkpoint Path", + "type": "string" + } + }, + "required": [ + "checkpoint_path" + ], + "title": "ValidateLoopsCheckpointRequestV1", + "type": "object" + }, + "ValidateLoopsCheckpointResponseV1": { + "description": "Response for ``POST /v1/loops/checkpoints/validate``. Empty on success;\ninaccessible or malformed paths raise 400.", + "properties": {}, + "title": "ValidateLoopsCheckpointResponseV1", + "type": "object" + }, + "LoopsCheckpointFilesResponseV1": { + "description": "Response with presigned URLs for files under a Loops checkpoint.", + "properties": { + "presigned_urls": { + "description": "List of presigned URLs for checkpoint files.", + "items": { + "$ref": "#/components/schemas/CheckpointFile" + }, + "title": "Presigned Urls", + "type": "array" }, - "seed": { + "next_page_token": { "anyOf": [ { "type": "integer" @@ -12132,17 +14946,45 @@ } ], "default": null, - "description": "Random seed for reproducibility.", - "title": "Seed" + "description": "Token to use for fetching the next page of results. None when there are no more results.", + "title": "Next Page Token" }, - "scale_down_delay_seconds": { - "default": 3600, - "description": "Seconds of inactivity before the run scales to zero. Must be positive. Defaults to 3600 (1 hour).", - "exclusiveMinimum": 0, - "title": "Scale Down Delay Seconds", + "total_count": { + "description": "Total number of checkpoint files available.", + "title": "Total Count", "type": "integer" + } + }, + "required": [ + "presigned_urls", + "total_count" + ], + "title": "LoopsCheckpointFilesResponseV1", + "type": "object" + }, + "LoopsDeploymentStatusV1": { + "description": "Latest deployment status for a Loops deployment.", + "properties": { + "name": { + "$ref": "#/components/schemas/Name", + "description": "Latest status of the Loops deployment." + } + }, + "required": [ + "name" + ], + "title": "LoopsDeploymentStatusV1", + "type": "object" + }, + "LoopsDeploymentV1": { + "description": "A Loops deployment \u2014 the long-lived run + sampler pair owned by a user.\n\nThe deployment's current sampler is included inline. The full list of\nsamplers visible to the caller (across all deployments) lives at\n``GET /v1/loops/samplers``.", + "properties": { + "id": { + "description": "The Loops deployment ID.", + "title": "Id", + "type": "string" }, - "path": { + "active_run_id": { "anyOf": [ { "type": "string" @@ -12152,90 +14994,124 @@ } ], "default": null, - "description": "Optional bt:// URI of an existing checkpoint to load weights from on startup. Form: bt://loops:/weights/.", - "examples": [ - "bt://loops:k4q95w5/weights/step-100" - ], - "title": "Path" + "description": "The ID of the run currently active on this deployment, if any. Null when the deployment's runs have been marked inactive (e.g. scale-to-zero) without a successor.", + "title": "Active Run Id" }, - "reuse_from_session_id": { + "base_model": { + "description": "The HuggingFace base model the deployment is fine-tuning.", + "title": "Base Model", + "type": "string" + }, + "base_url": { + "description": "The run's base URL.", + "title": "Base Url", + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/LoopsDeploymentStatusV1", + "description": "Latest deployment status." + }, + "user": { + "$ref": "#/components/schemas/UserV1", + "description": "The user who owns the Loops deployment." + }, + "sampler": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/LoopsSamplerV1" }, { "type": "null" } ], "default": null, - "description": "Optional Loops session ID whose trainer deployment should be reused for this run, sharing the infrastructure across sessions instead of provisioning fresh. The named session must belong to the same team. Reuse is best-effort: if the prior deployment is stopped, failed, or its sampler is unhealthy, a new deployment is provisioned instead.", - "title": "Reuse From Session Id" + "description": "The sampler bound to this deployment." } }, "required": [ - "session_id", - "base_model" + "id", + "base_model", + "base_url", + "status", + "user" ], - "title": "CreateLoopsRunRequestV1", + "title": "LoopsDeploymentV1", "type": "object" }, - "CreateLoopsRunResponseV1": { + "Name": { + "enum": [ + "CREATED", + "DEPLOYING", + "RUNNING", + "SCALED_TO_ZERO", + "FAILED", + "STOPPED" + ], + "title": "LoopsDeploymentStatus", + "type": "string" + }, + "ListLoopsDeploymentsResponseV1": { + "description": "Response for ``GET /v1/loops/deployments``.\n\nDefaults to the caller's own; pass ``?scope=org`` to list every deployment in\nthe caller's organization. Returns every deployment regardless of status;\nclients filter terminal states.", "properties": { - "run": { - "$ref": "#/components/schemas/LoopsRunV1" + "deployments": { + "description": "Active Loops deployments.", + "items": { + "$ref": "#/components/schemas/LoopsDeploymentV1" + }, + "title": "Deployments", + "type": "array" } }, "required": [ - "run" + "deployments" ], - "title": "CreateLoopsRunResponseV1", + "title": "ListLoopsDeploymentsResponseV1", "type": "object" }, - "GetLoopsRunResponseV1": { - "description": "Response for ``GET /v1/loops/runs/``.", + "DeactivateLoopsDeploymentResponseV1": { + "description": "Response for ``POST /v1/loops/deployments//deactivate``.", "properties": { - "run": { - "$ref": "#/components/schemas/LoopsRunV1", - "description": "The Loops run with its associated sampler." + "id": { + "description": "The deactivated Loops deployment ID.", + "title": "Id", + "type": "string" + }, + "base_model": { + "description": "The base model whose Loops deployment was deactivated.", + "title": "Base Model", + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/UserV1", + "description": "The user who owned the Loops deployment." } }, "required": [ - "run" + "id", + "base_model", + "user" ], - "title": "GetLoopsRunResponseV1", + "title": "DeactivateLoopsDeploymentResponseV1", "type": "object" }, - "ListLoopsSamplersResponseV1": { - "description": "Response for ``GET /v1/loops/samplers``.\n\nReturns the caller's samplers, including those paired to runs and\nstandalone samplers. Ordered newest-first.", + "GetLoopsDeploymentResponseV1": { + "description": "Response for ``GET /v1/loops/deployments/``.", "properties": { - "samplers": { - "description": "List of samplers.", - "items": { - "$ref": "#/components/schemas/LoopsSamplerV1" - }, - "title": "Samplers", - "type": "array" + "deployment": { + "$ref": "#/components/schemas/LoopsDeploymentV1", + "description": "The Loops deployment." } }, "required": [ - "samplers" + "deployment" ], - "title": "ListLoopsSamplersResponseV1", + "title": "GetLoopsDeploymentResponseV1", "type": "object" }, - "CreateLoopsSamplerRequestV1": { + "GetLoopsDeploymentMetricsRequestV1": { + "description": "Time-range request for trainer deployment metrics.", "properties": { - "session_id": { - "description": "ID of the Loops session this sampler belongs to.", - "title": "Session Id", - "type": "string" - }, - "base_model": { - "description": "Base model ID for standalone samplers (e.g., for baselines).", - "title": "Base Model", - "type": "string" - }, - "max_seq_length": { + "end_epoch_millis": { "anyOf": [ { "type": "integer" @@ -12245,740 +15121,818 @@ } ], "default": null, - "description": "Maximum prompt length (in tokens) the sampler must handle. Set this to the longest prompt you plan to send. Omit to use the default for the base model.", - "title": "Max Seq Length" + "description": "Epoch millis to end fetching metrics.", + "title": "End Epoch Millis" }, - "model_path": { + "start_epoch_millis": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Optional bt:// URI of an existing sampler-target checkpoint to load weights from on startup. Form: bt://loops:/sampler_weights/.", - "examples": [ - "bt://loops:k4q95w5/sampler_weights/step-100" + "description": "Epoch millis to start fetching metrics.", + "title": "Start Epoch Millis" + }, + "step_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } ], - "title": "Model Path" + "default": null, + "description": "Resolution of the returned series, in seconds. When omitted, a step is derived from the time range so large windows return fewer points.", + "title": "Step Seconds" }, - "reuse_from_session_id": { + "time_divisor_seconds": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Optional Loops session ID whose deployment should be reused for this sampler. Same best-effort semantics as the run endpoint.", - "title": "Reuse From Session Id" + "description": "Unit of time for request-volume metrics, in seconds (e.g. 60 for requests/minute). Defaults to per-second.", + "title": "Time Divisor Seconds" + } + }, + "title": "GetLoopsDeploymentMetricsRequestV1", + "type": "object" + }, + "InferenceVolumeByStatusDatapointV1": { + "description": "Request rate split by HTTP response code class.", + "properties": { + "timestamp": { + "description": "ISO 8601 timestamp.", + "format": "date-time", + "title": "Timestamp", + "type": "string" + }, + "status_2xx": { + "description": "2xx requests per second.", + "title": "Status 2Xx", + "type": "number" + }, + "status_4xx": { + "description": "4xx requests per second.", + "title": "Status 4Xx", + "type": "number" + }, + "status_5xx": { + "description": "5xx requests per second.", + "title": "Status 5Xx", + "type": "number" } }, "required": [ - "session_id", - "base_model" + "timestamp", + "status_2xx", + "status_4xx", + "status_5xx" ], - "title": "CreateLoopsSamplerRequestV1", + "title": "InferenceVolumeByStatusDatapointV1", "type": "object" }, - "CreateLoopsSamplerResponseV1": { + "LoopsDeploymentMetricsV1": { + "description": "Metrics for a trainer (Loops) deployment.\n\nService-level fields summarize HTTP traffic into the trainer pods (the\nKnative queue-proxy is the source). Compute fields are the leader-pod\naggregate; ``per_node_metrics`` carries the full multinode breakdown.", "properties": { - "sampler": { - "$ref": "#/components/schemas/LoopsSamplerV1" + "inference_volume": { + "description": "Number of inference requests per unit time (requests per second).", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Inference Volume", + "type": "array" + }, + "concurrent_requests": { + "description": "Number of in-progress concurrent inference requests. Source: the queue-proxy ``revision_queue_depth`` gauge on ``http-usermetric``.", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Concurrent Requests", + "type": "array" + }, + "response_time_stats": { + "description": "Percentiles of the response time distribution.", + "items": { + "$ref": "#/components/schemas/ResponseTimeDatapointV1" + }, + "title": "Response Time Stats", + "type": "array" + }, + "inference_volume_by_status": { + "description": "Request rate split by response code class.", + "items": { + "$ref": "#/components/schemas/InferenceVolumeByStatusDatapointV1" + }, + "title": "Inference Volume By Status", + "type": "array" + }, + "gpu_memory_usage_bytes": { + "additionalProperties": { + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "type": "array" + }, + "description": "Leader-pod GPU memory bytes per GPU rank.", + "title": "Gpu Memory Usage Bytes", + "type": "object" + }, + "gpu_utilization": { + "additionalProperties": { + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "type": "array" + }, + "description": "Leader-pod fractional GPU utilization per GPU rank.", + "title": "Gpu Utilization", + "type": "object" + }, + "cpu_usage": { + "description": "Leader-pod CPU usage in cores.", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Cpu Usage", + "type": "array" + }, + "cpu_memory_usage_bytes": { + "description": "Leader-pod CPU memory usage bytes.", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Cpu Memory Usage Bytes", + "type": "array" + }, + "ephemeral_storage": { + "$ref": "#/components/schemas/StorageMetricsV1", + "description": "Leader-pod ephemeral storage usage." + }, + "per_node_metrics": { + "description": "Per-node compute breakdown for multinode trainer deployments.", + "items": { + "$ref": "#/components/schemas/LoopsDeploymentNodeMetricsV1" + }, + "title": "Per Node Metrics", + "type": "array" } }, "required": [ - "sampler" + "inference_volume", + "concurrent_requests", + "response_time_stats", + "inference_volume_by_status", + "gpu_memory_usage_bytes", + "gpu_utilization", + "cpu_usage", + "cpu_memory_usage_bytes", + "ephemeral_storage", + "per_node_metrics" ], - "title": "CreateLoopsSamplerResponseV1", + "title": "LoopsDeploymentMetricsV1", "type": "object" }, - "GetLoopsSamplerResponseV1": { - "description": "Response for ``GET /v1/loops/samplers/``.", + "LoopsDeploymentNodeMetricsV1": { + "description": "Per-node compute metrics for a multinode trainer deployment.", "properties": { - "sampler": { - "$ref": "#/components/schemas/LoopsSamplerV1", - "description": "The Loops sampler." + "node_id": { + "description": "Identifier for the node.", + "title": "Node Id", + "type": "string" + }, + "gpu_memory_usage_bytes": { + "additionalProperties": { + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "type": "array" + }, + "description": "GPU memory usage bytes per GPU rank.", + "title": "Gpu Memory Usage Bytes", + "type": "object" + }, + "gpu_utilization": { + "additionalProperties": { + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "type": "array" + }, + "description": "Fractional GPU utilization per GPU rank.", + "title": "Gpu Utilization", + "type": "object" + }, + "cpu_usage": { + "description": "CPU usage in cores.", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Cpu Usage", + "type": "array" + }, + "cpu_memory_usage_bytes": { + "description": "CPU memory usage bytes.", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Cpu Memory Usage Bytes", + "type": "array" + }, + "ephemeral_storage": { + "$ref": "#/components/schemas/StorageMetricsV1", + "description": "Ephemeral storage usage." } }, "required": [ - "sampler" + "node_id", + "gpu_memory_usage_bytes", + "gpu_utilization", + "cpu_usage", + "cpu_memory_usage_bytes", + "ephemeral_storage" ], - "title": "GetLoopsSamplerResponseV1", + "title": "LoopsDeploymentNodeMetricsV1", "type": "object" }, - "LoopsCheckpointV1": { - "description": "A checkpoint saved by a Loops run.", + "ResponseTimeDatapointV1": { + "description": "Latency quantile datapoint.\n\nValues are reported in **milliseconds** to match the oracle/inference\n``response_time_stats`` convention. Source histogram is the queue-proxy's\n``revision_request_latencies_bucket`` whose bucket boundaries are in ms.", "properties": { - "checkpoint_id": { - "description": "The ID of the checkpoint.", - "title": "Checkpoint Id", - "type": "string" - }, - "created_at": { - "description": "The timestamp of the checkpoint in ISO 8601 format.", + "timestamp": { + "description": "ISO 8601 timestamp.", "format": "date-time", - "title": "Created At", - "type": "string" - }, - "checkpoint_type": { - "description": "The type of checkpoint.", - "title": "Checkpoint Type", + "title": "Timestamp", "type": "string" }, - "base_model": { + "p50": { "anyOf": [ { - "type": "string" + "type": "number" }, { "type": "null" } ], - "description": "The base model of the checkpoint.", - "title": "Base Model" + "default": null, + "description": "50th percentile request latency (milliseconds).", + "title": "P50" }, - "lora_adapter_config": { + "p95": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "type": "number" }, { "type": "null" } ], - "description": "The adapter config of the checkpoint.", - "title": "Lora Adapter Config" - }, - "size_bytes": { - "description": "The size of the checkpoint in bytes.", - "title": "Size Bytes", - "type": "integer" + "default": null, + "description": "95th percentile request latency (milliseconds).", + "title": "P95" }, - "sync_status": { + "p99": { "anyOf": [ { - "type": "string" + "type": "number" }, { "type": "null" } ], "default": null, - "description": "Sync state of the checkpoint: SYNCING or COMPLETE.", - "title": "Sync Status" - }, - "id": { - "description": "The checkpoint ID.", - "title": "Id", - "type": "string" - }, - "run_id": { - "description": "The ID of the run that produced the checkpoint.", - "title": "Run Id", - "type": "string" - }, - "target": { - "$ref": "#/components/schemas/TrainerCheckpointTarget", - "description": "Whether this checkpoint is loadable by the sampler or by the run." + "description": "99th percentile request latency (milliseconds).", + "title": "P99" } }, "required": [ - "checkpoint_id", - "created_at", - "checkpoint_type", - "base_model", - "lora_adapter_config", - "size_bytes", - "id", - "run_id", - "target" + "timestamp" ], - "title": "LoopsCheckpointV1", + "title": "ResponseTimeDatapointV1", "type": "object" }, - "ListLoopsCheckpointsResponseV1": { - "description": "Checkpoints matching the query filter.", + "GetLoopsDeploymentMetricsResponseV1": { + "description": "Response for ``POST /v1/loops/deployments//metrics``.", "properties": { - "checkpoints": { - "description": "Matching checkpoints.", - "items": { - "$ref": "#/components/schemas/LoopsCheckpointV1" - }, - "title": "Checkpoints", - "type": "array" + "deployment_id": { + "description": "The trainer deployment ID.", + "title": "Deployment Id", + "type": "string" + }, + "metrics": { + "$ref": "#/components/schemas/LoopsDeploymentMetricsV1", + "description": "Metrics for the deployment." } }, "required": [ - "checkpoints" + "deployment_id", + "metrics" ], - "title": "ListLoopsCheckpointsResponseV1", + "title": "GetLoopsDeploymentMetricsResponseV1", "type": "object" }, - "ListLoopsCheckpointsQueryParamsV1": { - "description": "Query-string filters for ``GET /v1/loops/checkpoints``.\n\nProvide exactly one of ``run_id`` (all checkpoints for the run),\n``base_model`` (all checkpoints across the caller's runs of that\nbase model), or ``checkpoint_path`` (the single matching checkpoint).", + "GetLoopsDeploymentLogsRequestV1": { + "description": "Query parameters for fetching a Loops deployment's logs.", "properties": { - "run_id": { + "start_epoch_millis": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Filter by run ID. Returns all checkpoints saved by the run.", - "examples": [ - "k4q95w5" - ], - "title": "Run Id" + "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + "title": "Start Epoch Millis" }, - "base_model": { + "end_epoch_millis": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Filter by base model. Returns checkpoints across the caller's runs of this base model.", - "examples": [ - "Qwen/Qwen3-8B" - ], - "title": "Base Model" + "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + "title": "End Epoch Millis" }, - "checkpoint_path": { + "direction": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/SortOrderV1" }, { "type": "null" } ], "default": null, - "description": "bt:// URI of a Loops checkpoint. Form: bt://loops:/(weights|sampler_weights)/.", - "examples": [ - "bt://loops:k4q95w5/sampler_weights/step-100" - ], - "title": "Checkpoint Path" - } - }, - "title": "ListLoopsCheckpointsQueryParamsV1", - "type": "object" - }, - "ValidateLoopsCheckpointRequestV1": { - "description": "Request body for ``POST /v1/loops/checkpoints/validate``.", - "properties": { - "checkpoint_path": { - "description": "bt:// URI of a sampler checkpoint. Form: bt://loops:/sampler_weights/.", - "examples": [ - "bt://loops:k4q95w5/sampler_weights/step-100" - ], - "title": "Checkpoint Path", - "type": "string" - } - }, - "required": [ - "checkpoint_path" - ], - "title": "ValidateLoopsCheckpointRequestV1", - "type": "object" - }, - "ValidateLoopsCheckpointResponseV1": { - "description": "Response for ``POST /v1/loops/checkpoints/validate``. Empty on success;\ninaccessible or malformed paths raise 400.", - "properties": {}, - "title": "ValidateLoopsCheckpointResponseV1", - "type": "object" - }, - "LoopsCheckpointFilesResponseV1": { - "description": "Response with presigned URLs for files under a Loops checkpoint.", - "properties": { - "presigned_urls": { - "description": "List of presigned URLs for checkpoint files.", - "items": { - "$ref": "#/components/schemas/CheckpointFile" - }, - "title": "Presigned Urls", - "type": "array" + "description": "Sort order for logs" }, - "next_page_token": { + "limit": { "anyOf": [ { + "maximum": 1000, + "minimum": 1, "type": "integer" }, { "type": "null" } ], + "default": 500, + "description": "Limit of logs to fetch in a single request", + "title": "Limit" + }, + "min_level": { + "anyOf": [ + { + "$ref": "#/components/schemas/LogLevelV1" + }, + { + "type": "null" + } + ], "default": null, - "description": "Token to use for fetching the next page of results. None when there are no more results.", - "title": "Next Page Token" + "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." + } + }, + "title": "GetLoopsDeploymentLogsRequestV1", + "type": "object" + }, + "TeamTrainingGpuCapacityItemV1": { + "description": "Per-team GPU capacity and current usage for one GPU type.", + "properties": { + "team_id": { + "description": "Team identifier", + "title": "Team Id", + "type": "string" }, - "total_count": { - "description": "Total number of checkpoint files available.", - "title": "Total Count", + "team_name": { + "description": "Team name", + "title": "Team Name", + "type": "string" + }, + "gpu_type": { + "description": "GPU type identifier (e.g. H100, A100-40GB)", + "title": "Gpu Type", + "type": "string" + }, + "baseline": { + "description": "Baseline GPU allocation for the team. 0 if not configured.", + "title": "Baseline", + "type": "integer" + }, + "limit": { + "description": "Maximum concurrent GPUs of this type for this team", + "title": "Limit", + "type": "integer" + }, + "usage_count": { + "description": "GPUs currently in use by the team's active training jobs", + "title": "Usage Count", "type": "integer" } }, "required": [ - "presigned_urls", - "total_count" - ], - "title": "LoopsCheckpointFilesResponseV1", - "type": "object" - }, - "LoopsDeploymentStatusV1": { - "description": "Latest deployment status for a Loops deployment.", - "properties": { - "name": { - "$ref": "#/components/schemas/Name", - "description": "Latest status of the Loops deployment." - } - }, - "required": [ - "name" + "team_id", + "team_name", + "gpu_type", + "baseline", + "limit", + "usage_count" ], - "title": "LoopsDeploymentStatusV1", + "title": "TeamTrainingGpuCapacityItemV1", "type": "object" }, - "LoopsDeploymentV1": { - "description": "A Loops deployment \u2014 the long-lived run + sampler pair owned by a user.\n\nThe deployment's current sampler is included inline. The full list of\nsamplers visible to the caller (across all deployments) lives at\n``GET /v1/loops/samplers``.", + "TrainingGpuCapacityItemV1": { + "description": "GPU capacity and current usage for one GPU type.", "properties": { - "id": { - "description": "The Loops deployment ID.", - "title": "Id", - "type": "string" - }, - "base_model": { - "description": "The HuggingFace base model the deployment is fine-tuning.", - "title": "Base Model", + "gpu_type": { + "description": "GPU type identifier (e.g. H100, A100-40GB)", + "title": "Gpu Type", "type": "string" }, - "base_url": { - "description": "The run's base URL.", - "title": "Base Url", - "type": "string" + "baseline": { + "description": "Baseline GPU allocation; jobs below this threshold are expected to run immediately. 0 if not configured.", + "title": "Baseline", + "type": "integer" }, - "status": { - "$ref": "#/components/schemas/LoopsDeploymentStatusV1", - "description": "Latest deployment status." + "limit": { + "description": "Maximum concurrent GPUs of this type for this org", + "title": "Limit", + "type": "integer" }, - "sampler": { - "$ref": "#/components/schemas/LoopsSamplerV1", - "description": "The sampler bound to this deployment." + "usage_count": { + "description": "GPUs currently in use by active training jobs", + "title": "Usage Count", + "type": "integer" } }, "required": [ - "id", - "base_model", - "base_url", - "status", - "sampler" + "gpu_type", + "baseline", + "limit", + "usage_count" ], - "title": "LoopsDeploymentV1", + "title": "TrainingGpuCapacityItemV1", "type": "object" }, - "Name": { - "enum": [ - "CREATED", - "DEPLOYING", - "RUNNING", - "SCALED_TO_ZERO", - "FAILED", - "STOPPED" - ], - "title": "LoopsDeploymentStatus", - "type": "string" - }, - "ListLoopsDeploymentsResponseV1": { - "description": "Response for ``GET /v1/loops/deployments``.\n\nReturns every Loops deployment owned by the caller, regardless of status\n(CREATED, DEPLOYING, RUNNING, STOPPED, or FAILED). Clients filter\nterminal-state deployments themselves.", + "GetTrainingGpuCapacityResponseV1": { + "description": "Response for the training GPU capacity endpoint.", "properties": { - "deployments": { - "description": "Active Loops deployments.", + "gpu_capacities": { + "description": "Org-level GPU capacity limits and current usage per GPU type", "items": { - "$ref": "#/components/schemas/LoopsDeploymentV1" + "$ref": "#/components/schemas/TrainingGpuCapacityItemV1" }, - "title": "Deployments", + "title": "Gpu Capacities", + "type": "array" + }, + "team_gpu_capacities": { + "description": "Per-team GPU capacity limits and current usage per GPU type", + "items": { + "$ref": "#/components/schemas/TeamTrainingGpuCapacityItemV1" + }, + "title": "Team Gpu Capacities", "type": "array" } }, "required": [ - "deployments" + "gpu_capacities" ], - "title": "ListLoopsDeploymentsResponseV1", + "title": "GetTrainingGpuCapacityResponseV1", "type": "object" }, - "DeactivateLoopsDeploymentResponseV1": { - "description": "Response for ``POST /v1/loops/deployments//deactivate``.", + "PatchTeamTrainingGpuCapacityRequestV1": { + "description": "A request to set the GPU capacity ceiling for a (team, gpu_type) pair.\n\nCreates the limit if one doesn't already exist for this team and GPU type,\notherwise updates it in place.", "properties": { - "id": { - "description": "The deactivated Loops deployment ID.", - "title": "Id", + "team_id": { + "description": "Team identifier", + "title": "Team Id", "type": "string" }, - "base_model": { - "description": "The base model whose Loops deployment was deactivated.", - "title": "Base Model", + "gpu_type": { + "description": "GPU type identifier (e.g. H100, A100-40GB)", + "title": "Gpu Type", "type": "string" }, - "user": { - "$ref": "#/components/schemas/UserV1", - "description": "The user who owned the Loops deployment." + "max_gpus": { + "description": "Max concurrent GPUs of this type the team may use", + "examples": [ + 8, + 16, + 32 + ], + "title": "Max Gpus", + "type": "integer" } }, "required": [ - "id", - "base_model", - "user" + "team_id", + "gpu_type", + "max_gpus" ], - "title": "DeactivateLoopsDeploymentResponseV1", + "title": "PatchTeamTrainingGpuCapacityRequestV1", "type": "object" }, - "GetLoopsDeploymentResponseV1": { - "description": "Response for ``GET /v1/loops/deployments/``.", + "PatchTeamTrainingGpuCapacityResponseV1": { + "description": "Response for setting a team's GPU capacity ceiling.", "properties": { - "deployment": { - "$ref": "#/components/schemas/LoopsDeploymentV1", - "description": "The Loops deployment." + "team_gpu_capacity": { + "$ref": "#/components/schemas/TeamTrainingGpuCapacityItemV1", + "description": "The updated per-team GPU capacity limit" } }, "required": [ - "deployment" + "team_gpu_capacity" ], - "title": "GetLoopsDeploymentResponseV1", + "title": "PatchTeamTrainingGpuCapacityResponseV1", "type": "object" }, - "GetLoopsDeploymentMetricsRequestV1": { - "description": "Time-range request for trainer deployment metrics.", + "ActiveJobAtSubmitV1": { + "description": "One other job in the same (org, gpu_type) pool that was holding GPU\ncapacity at the moment the target was submitted.", "properties": { - "end_epoch_millis": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Epoch millis to end fetching metrics.", - "title": "End Epoch Millis" + "training_job_id": { + "description": "Hashid of the other training job", + "title": "Training Job Id", + "type": "string" }, - "start_epoch_millis": { + "training_job_name": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Epoch millis to start fetching metrics.", - "title": "Start Epoch Millis" - } - }, - "title": "GetLoopsDeploymentMetricsRequestV1", - "type": "object" - }, - "InferenceVolumeByStatusDatapointV1": { - "description": "Request rate split by HTTP response code class.", - "properties": { - "timestamp": { - "description": "ISO 8601 timestamp.", - "format": "date-time", - "title": "Timestamp", + "description": "Other job's name", + "title": "Training Job Name" + }, + "instance_type_name": { + "description": "Instance type of the other job", + "title": "Instance Type Name", "type": "string" }, - "status_2xx": { - "description": "2xx requests per second.", - "title": "Status 2Xx", - "type": "number" + "total_gpus": { + "description": "gpu_count * effective_node_count", + "title": "Total Gpus", + "type": "integer" }, - "status_4xx": { - "description": "4xx requests per second.", - "title": "Status 4Xx", - "type": "number" + "workload_plane_name": { + "description": "Workload plane the other job was on", + "title": "Workload Plane Name", + "type": "string" }, - "status_5xx": { - "description": "5xx requests per second.", - "title": "Status 5Xx", - "type": "number" + "status_at_submit": { + "description": "Other job's status as of submitted_at (one of ACTIVE_STATES)", + "title": "Status At Submit", + "type": "string" + }, + "status_set_at": { + "description": "When that status was set", + "format": "date-time", + "title": "Status Set At", + "type": "string" } }, "required": [ - "timestamp", - "status_2xx", - "status_4xx", - "status_5xx" + "training_job_id", + "instance_type_name", + "total_gpus", + "workload_plane_name", + "status_at_submit", + "status_set_at" ], - "title": "InferenceVolumeByStatusDatapointV1", + "title": "ActiveJobAtSubmitV1", "type": "object" - }, - "LoopsDeploymentMetricsV1": { - "description": "Metrics for a trainer (Loops) deployment.\n\nService-level fields summarize HTTP traffic into the trainer pods (the\nKnative queue-proxy is the source). Compute fields are the leader-pod\naggregate; ``per_node_metrics`` carries the full multinode breakdown.", - "properties": { - "inference_volume": { - "description": "Number of inference requests per unit time (requests per second).", - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "title": "Inference Volume", - "type": "array" - }, - "concurrent_requests": { - "description": "Number of in-progress concurrent inference requests. Source: the queue-proxy ``revision_queue_depth`` gauge on ``http-usermetric``.", - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "title": "Concurrent Requests", - "type": "array" - }, - "response_time_stats": { - "description": "Percentiles of the response time distribution.", - "items": { - "$ref": "#/components/schemas/ResponseTimeDatapointV1" - }, - "title": "Response Time Stats", - "type": "array" - }, - "inference_volume_by_status": { - "description": "Request rate split by response code class.", - "items": { - "$ref": "#/components/schemas/InferenceVolumeByStatusDatapointV1" - }, - "title": "Inference Volume By Status", - "type": "array" - }, - "gpu_memory_usage_bytes": { - "additionalProperties": { - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "type": "array" - }, - "description": "Leader-pod GPU memory bytes per GPU rank.", - "title": "Gpu Memory Usage Bytes", - "type": "object" - }, - "gpu_utilization": { - "additionalProperties": { - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "type": "array" - }, - "description": "Leader-pod fractional GPU utilization per GPU rank.", - "title": "Gpu Utilization", - "type": "object" - }, - "cpu_usage": { - "description": "Leader-pod CPU usage in cores.", - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "title": "Cpu Usage", - "type": "array" + }, + "CapacityAtSubmitV1": { + "description": "A GPU capacity row as it stands now, with ``last_modified`` so callers\ncan judge whether the value matches what the dequeue gate saw at submit\ntime. Capacity rows are not historicized: edits overwrite in place. Compare\n``last_modified`` against the response's ``submitted_at`` \u2014 if it's later,\nthe value may have changed.", + "properties": { + "gpu_type": { + "description": "GPU type identifier (e.g. H100, A100-40GB)", + "title": "Gpu Type", + "type": "string" }, - "cpu_memory_usage_bytes": { - "description": "Leader-pod CPU memory usage bytes.", - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "title": "Cpu Memory Usage Bytes", - "type": "array" + "max_gpus": { + "description": "Current max concurrent GPUs of this type", + "title": "Max Gpus", + "type": "integer" }, - "ephemeral_storage": { - "$ref": "#/components/schemas/StorageMetricsV1", - "description": "Leader-pod ephemeral storage usage." + "min_gpus": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Current baseline GPU allocation, if configured", + "title": "Min Gpus" }, - "per_node_metrics": { - "description": "Per-node compute breakdown for multinode trainer deployments.", - "items": { - "$ref": "#/components/schemas/LoopsDeploymentNodeMetricsV1" - }, - "title": "Per Node Metrics", - "type": "array" + "last_modified": { + "description": "When the capacity row was last modified", + "format": "date-time", + "title": "Last Modified", + "type": "string" } }, "required": [ - "inference_volume", - "concurrent_requests", - "response_time_stats", - "inference_volume_by_status", - "gpu_memory_usage_bytes", - "gpu_utilization", - "cpu_usage", - "cpu_memory_usage_bytes", - "ephemeral_storage", - "per_node_metrics" + "gpu_type", + "max_gpus", + "last_modified" ], - "title": "LoopsDeploymentMetricsV1", + "title": "CapacityAtSubmitV1", "type": "object" }, - "LoopsDeploymentNodeMetricsV1": { - "description": "Per-node compute metrics for a multinode trainer deployment.", + "PendingJobAheadAtSubmitV1": { + "description": "A PENDING job in the same (org, gpu_type) pool that was ahead of the\ntarget in dequeue FIFO order at submitted_at \u2014 higher priority, or same\npriority and earlier submission.", "properties": { - "node_id": { - "description": "Identifier for the node.", - "title": "Node Id", + "training_job_id": { + "description": "Hashid of the other training job", + "title": "Training Job Id", "type": "string" }, - "gpu_memory_usage_bytes": { - "additionalProperties": { - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" + "training_job_name": { + "anyOf": [ + { + "type": "string" }, - "type": "array" - }, - "description": "GPU memory usage bytes per GPU rank.", - "title": "Gpu Memory Usage Bytes", - "type": "object" + { + "type": "null" + } + ], + "default": null, + "description": "Other job's name", + "title": "Training Job Name" }, - "gpu_utilization": { - "additionalProperties": { - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "type": "array" - }, - "description": "Fractional GPU utilization per GPU rank.", - "title": "Gpu Utilization", - "type": "object" + "instance_type_name": { + "description": "Instance type of the other job", + "title": "Instance Type Name", + "type": "string" }, - "cpu_usage": { - "description": "CPU usage in cores.", - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "title": "Cpu Usage", - "type": "array" + "requested_gpus": { + "description": "gpu_count * effective_node_count", + "title": "Requested Gpus", + "type": "integer" }, - "cpu_memory_usage_bytes": { - "description": "CPU memory usage bytes.", - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "title": "Cpu Memory Usage Bytes", - "type": "array" + "priority": { + "description": "Effective priority (NULL coalesced to 0)", + "title": "Priority", + "type": "integer" }, - "ephemeral_storage": { - "$ref": "#/components/schemas/StorageMetricsV1", - "description": "Ephemeral storage usage." + "submitted_at": { + "description": "The other job's submission time", + "format": "date-time", + "title": "Submitted At", + "type": "string" } }, "required": [ - "node_id", - "gpu_memory_usage_bytes", - "gpu_utilization", - "cpu_usage", - "cpu_memory_usage_bytes", - "ephemeral_storage" + "training_job_id", + "instance_type_name", + "requested_gpus", + "priority", + "submitted_at" ], - "title": "LoopsDeploymentNodeMetricsV1", + "title": "PendingJobAheadAtSubmitV1", "type": "object" }, - "ResponseTimeDatapointV1": { - "description": "Latency quantile datapoint.\n\nValues are reported in **milliseconds** to match the oracle/inference\n``response_time_stats`` convention. Source histogram is the queue-proxy's\n``revision_request_latencies_bucket`` whose bucket boundaries are in ms.", + "QueueEventV1": { + "description": "A single ``TrainingJobStatus`` row inside the queue-context window.", "properties": { - "timestamp": { - "description": "ISO 8601 timestamp.", - "format": "date-time", - "title": "Timestamp", + "training_job_id": { + "description": "Hashid of the training job this event is for", + "title": "Training Job Id", "type": "string" }, - "p50": { + "training_job_name": { "anyOf": [ { - "type": "number" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "50th percentile request latency (milliseconds).", - "title": "P50" + "description": "Job name", + "title": "Training Job Name" }, - "p95": { + "status": { + "description": "TrainingJobStatus.Name value", + "title": "Status", + "type": "string" + }, + "created": { + "description": "When the status row was inserted", + "format": "date-time", + "title": "Created", + "type": "string" + }, + "event_message": { "anyOf": [ { - "type": "number" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "95th percentile request latency (milliseconds).", - "title": "P95" + "description": "Human-readable event message from the status metadata", + "title": "Event Message" }, - "p99": { + "exit_code": { "anyOf": [ { - "type": "number" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "99th percentile request latency (milliseconds).", - "title": "P99" + "description": "Exit code from the status metadata, if any", + "title": "Exit Code" } }, "required": [ - "timestamp" + "training_job_id", + "status", + "created" ], - "title": "ResponseTimeDatapointV1", + "title": "QueueEventV1", "type": "object" }, - "GetLoopsDeploymentMetricsResponseV1": { - "description": "Response for ``POST /v1/loops/deployments//metrics``.", + "GetTrainingJobQueueContextResponseV1": { + "description": "Read-only diagnostic for a training job's PENDING window.\n\nReturns the (org, gpu_type) capacity pool the job was gated by, jobs that\nwere holding GPU capacity in that pool when this job was submitted, and\nevery status event in [submitted_at, released_at] for those jobs (or up to\n\"now\" if the target is still PENDING).", "properties": { - "deployment_id": { - "description": "The trainer deployment ID.", - "title": "Deployment Id", + "target_job_id": { + "description": "Hashid of the target training job", + "title": "Target Job Id", "type": "string" }, - "metrics": { - "$ref": "#/components/schemas/LoopsDeploymentMetricsV1", - "description": "Metrics for the deployment." - } - }, - "required": [ - "deployment_id", - "metrics" - ], - "title": "GetLoopsDeploymentMetricsResponseV1", - "type": "object" - }, - "GetLoopsDeploymentLogsRequestV1": { - "description": "Query parameters for fetching a Loops deployment's logs.", - "properties": { - "start_epoch_millis": { + "target_job_name": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Epoch millis timestamp to start fetching logs", - "title": "Start Epoch Millis" + "description": "Target job's name", + "title": "Target Job Name" }, - "end_epoch_millis": { + "gpu_type": { + "description": "GPU type the target requested", + "title": "Gpu Type", + "type": "string" + }, + "requested_gpus": { + "description": "GPUs the target requested (gpu_count * effective_node_count)", + "title": "Requested Gpus", + "type": "integer" + }, + "submitted_at": { + "description": "When the job row was inserted (= API POST time)", + "format": "date-time", + "title": "Submitted At", + "type": "string" + }, + "released_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "When the job's TRAINING_JOB_CREATED status was set, i.e. the moment it was released from PENDING. None if still PENDING.", + "title": "Released At" + }, + "pending_seconds": { "anyOf": [ { "type": "integer" @@ -12988,89 +15942,75 @@ } ], "default": null, - "description": "Epoch millis timestamp to end fetching logs", - "title": "End Epoch Millis" + "description": "released_at - submitted_at in seconds. None if still PENDING.", + "title": "Pending Seconds" }, - "direction": { + "org_capacity": { "anyOf": [ { - "$ref": "#/components/schemas/SortOrderV1" + "$ref": "#/components/schemas/CapacityAtSubmitV1" }, { "type": "null" } ], "default": null, - "description": "Sort order for logs" + "description": "Org-level cap for (org, gpu_type). None if no cap is configured." }, - "limit": { + "team_capacity": { "anyOf": [ { - "maximum": 1000, - "minimum": 1, - "type": "integer" + "$ref": "#/components/schemas/CapacityAtSubmitV1" }, { "type": "null" } ], - "default": 500, - "description": "Limit of logs to fetch in a single request", - "title": "Limit" - } - }, - "title": "GetLoopsDeploymentLogsRequestV1", - "type": "object" - }, - "TrainingGpuCapacityItemV1": { - "description": "GPU capacity and current usage for one GPU type.", - "properties": { - "gpu_type": { - "description": "GPU type identifier (e.g. H100, A100-40GB)", - "title": "Gpu Type", - "type": "string" + "default": null, + "description": "Team-level cap for (team, gpu_type). None if no team cap is configured." }, - "baseline": { - "description": "Baseline GPU allocation; jobs below this threshold are expected to run immediately. 0 if not configured.", - "title": "Baseline", - "type": "integer" + "active_at_submit": { + "description": "Jobs in the same (org, gpu_type) pool that were holding capacity at submitted_at", + "items": { + "$ref": "#/components/schemas/ActiveJobAtSubmitV1" + }, + "title": "Active At Submit", + "type": "array" }, - "limit": { - "description": "Maximum concurrent GPUs of this type for this org", - "title": "Limit", - "type": "integer" + "pending_ahead_at_submit": { + "description": "PENDING jobs in the same (org, gpu_type) pool that were ahead of the target in dequeue FIFO order at submitted_at (priority DESC then created ASC). These also block the target's release.", + "items": { + "$ref": "#/components/schemas/PendingJobAheadAtSubmitV1" + }, + "title": "Pending Ahead At Submit", + "type": "array" }, - "usage_count": { - "description": "GPUs currently in use by active training jobs", - "title": "Usage Count", - "type": "integer" - } - }, - "required": [ - "gpu_type", - "baseline", - "limit", - "usage_count" - ], - "title": "TrainingGpuCapacityItemV1", - "type": "object" - }, - "GetTrainingGpuCapacityResponseV1": { - "description": "Response for the training GPU capacity endpoint.", - "properties": { - "gpu_capacities": { - "description": "GPU capacity limits and current usage per GPU type", + "events": { + "description": "Every status event in [submitted_at, events_window_end] for the target job, every job in active_at_submit, and every job in pending_ahead_at_submit, oldest first.", "items": { - "$ref": "#/components/schemas/TrainingGpuCapacityItemV1" + "$ref": "#/components/schemas/QueueEventV1" }, - "title": "Gpu Capacities", + "title": "Events", "type": "array" + }, + "events_window_end": { + "description": "released_at if set, else 'now' (events ongoing)", + "format": "date-time", + "title": "Events Window End", + "type": "string" } }, "required": [ - "gpu_capacities" - ], - "title": "GetTrainingGpuCapacityResponseV1", + "target_job_id", + "gpu_type", + "requested_gpus", + "submitted_at", + "active_at_submit", + "pending_ahead_at_submit", + "events", + "events_window_end" + ], + "title": "GetTrainingJobQueueContextResponseV1", "type": "object" }, "GetBlobCredentialsResponseV1": { @@ -13249,6 +16189,18 @@ "default": null, "description": "The name of the team associated with the API key", "title": "Team Name" + }, + "owner": { + "anyOf": [ + { + "$ref": "#/components/schemas/APIKeyOwnerV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The user who owns the API key. Only present for personal API keys." } }, "required": [ @@ -13258,6 +16210,47 @@ "title": "APIKeyInfoV1", "type": "object" }, + "APIKeyOwnerV1": { + "description": "The user who owns a personal API key.", + "properties": { + "user_id": { + "description": "Unique identifier for the user", + "title": "User Id", + "type": "string" + }, + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Email address of the user", + "title": "Email" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Display name of the user", + "title": "Name" + } + }, + "required": [ + "user_id" + ], + "title": "APIKeyOwnerV1", + "type": "object" + }, "APIKeysV1": { "description": "A list of API keys.", "properties": { @@ -13340,8 +16333,279 @@ "title": "CreateModelWeightSnapshotRequestV1", "type": "object" }, + "LimitTypeV1": { + "enum": [ + "REQUEST", + "TOKEN" + ], + "title": "LimitTypeV1", + "type": "string" + }, + "ModelAPIOrgDetailsV1": { + "description": "Workspace-specific state for a Model API.", + "properties": { + "added_at": { + "description": "When the workspace first added this Model API.", + "format": "date-time", + "title": "Added At", + "type": "string" + }, + "last_used_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "When the workspace last invoked this Model API. Null if the workspace has never invoked it.", + "title": "Last Used At" + } + }, + "required": [ + "added_at" + ], + "title": "ModelAPIOrgDetailsV1", + "type": "object" + }, + "ModelAPIV1": { + "description": "A Model API catalog row, optionally enriched with workspace-specific state.", + "properties": { + "name": { + "description": "Identifier of the Model API. Stable, URL-safe slug used as the public identifier.", + "examples": [ + "llama-3-3-70b-instruct" + ], + "title": "Name", + "type": "string" + }, + "display_name": { + "description": "Human-readable name of the Model API.", + "examples": [ + "Llama 3.3 70B Instruct" + ], + "title": "Display Name", + "type": "string" + }, + "description": { + "description": "Description of the Model API.", + "title": "Description", + "type": "string" + }, + "model_family": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Family the underlying model belongs to.", + "examples": [ + "META", + "DEEPSEEK", + "QWEN" + ], + "title": "Model Family" + }, + "release_date": { + "description": "Date the Model API was made available.", + "format": "date", + "title": "Release Date", + "type": "string" + }, + "invoke_url": { + "description": "Base URL for invoking the Model API. OpenAI-shaped routes (e.g. /v1/chat/completions) live underneath this host.", + "examples": [ + "https://inference.baseten.co" + ], + "title": "Invoke Url", + "type": "string" + }, + "context_length": { + "description": "The model's context window length, in tokens.", + "examples": [ + 8192 + ], + "title": "Context Length", + "type": "integer" + }, + "cost_per_million_input_tokens": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Cost per million input tokens, in dollars.", + "examples": [ + "0.13" + ], + "title": "Cost Per Million Input Tokens" + }, + "cost_per_million_output_tokens": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Cost per million output tokens, in dollars.", + "examples": [ + "0.50" + ], + "title": "Cost Per Million Output Tokens" + }, + "rate_limits": { + "description": "Rate limits in effect for the workspace. Workspace-specific overrides are returned when the workspace has added this Model API and configured them; otherwise the catalog default rate limits are returned.", + "items": { + "$ref": "#/components/schemas/RateLimitV1" + }, + "title": "Rate Limits", + "type": "array" + }, + "org_details": { + "anyOf": [ + { + "$ref": "#/components/schemas/ModelAPIOrgDetailsV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Workspace-specific state. Null when the workspace has not added this Model API." + } + }, + "required": [ + "name", + "display_name", + "description", + "release_date", + "invoke_url", + "context_length", + "cost_per_million_input_tokens", + "cost_per_million_output_tokens", + "rate_limits" + ], + "title": "ModelAPIV1", + "type": "object" + }, + "RateLimitUnitV1": { + "enum": [ + "SECOND", + "MINUTE" + ], + "title": "RateLimitUnitV1", + "type": "string" + }, + "RateLimitV1": { + "properties": { + "type": { + "$ref": "#/components/schemas/LimitTypeV1", + "description": "The type of the rate limit", + "examples": [ + "TOKEN", + "REQUEST" + ] + }, + "unit": { + "$ref": "#/components/schemas/RateLimitUnitV1", + "description": "The unit of the rate limit", + "examples": [ + "SECOND", + "MINUTE" + ] + }, + "threshold": { + "description": "The threshold for the rate limit", + "examples": [ + 1000, + 50000 + ], + "minimum": 0, + "title": "Threshold", + "type": "integer" + } + }, + "required": [ + "type", + "unit", + "threshold" + ], + "title": "RateLimitV1", + "type": "object" + }, + "ModelAPIsResponseV1": { + "description": "Page of Model APIs visible to the caller.", + "properties": { + "items": { + "description": "Items in this page.", + "items": { + "$ref": "#/components/schemas/ModelAPIV1" + }, + "title": "Items", + "type": "array" + }, + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." + } + }, + "required": [ + "items", + "pagination" + ], + "title": "ModelAPIsResponseV1", + "type": "object" + }, + "ModelAPIsRequestV1": { + "description": "Query-string filters for ``GET /v1/model_apis``.", + "properties": { + "cursor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "title": "Cursor" + }, + "limit": { + "default": 100, + "description": "Maximum number of items to return.", + "maximum": 1000, + "minimum": 1, + "title": "Limit", + "type": "integer" + }, + "added_only": { + "default": false, + "description": "When true, restrict the result to Model APIs the workspace has added. Defaults to the full visible catalog.", + "title": "Added Only", + "type": "boolean" + } + }, + "title": "ModelAPIsRequestV1", + "type": "object" + }, "CreateLLMModelRequestV1": { - "description": "A request to create a BIS LLM model", + "description": "A request to create a BIS-LLM model", "properties": { "resources": { "additionalProperties": true, @@ -13350,10 +16614,17 @@ "type": "object" }, "llm_version": { - "default": "1.0", - "description": "Version of the helm chart to use", - "title": "Llm Version", - "type": "string" + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Version of the helm chart to use.", + "title": "Llm Version" }, "llm_config": { "additionalProperties": true, @@ -13488,7 +16759,7 @@ "type": "object" }, "LLMModelHandleV1": { - "description": "Handle for a BIS LLM model deployment.", + "description": "Handle for a BIS-LLM model deployment.", "properties": { "model_id": { "description": "Unique identifier of the model", @@ -13528,7 +16799,7 @@ "type": "object" }, "CreateLLMModelVersionRequestV1": { - "description": "A request to create a BIS LLM model version", + "description": "A request to create a BIS-LLM model version", "properties": { "resources": { "additionalProperties": true, @@ -13537,10 +16808,17 @@ "type": "object" }, "llm_version": { - "default": "1.0", - "description": "Version of the helm chart to use", - "title": "Llm Version", - "type": "string" + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Version of the helm chart to use.", + "title": "Llm Version" }, "llm_config": { "additionalProperties": true, @@ -13686,6 +16964,11 @@ "title": "Is Public", "type": "boolean" }, + "closed_source": { + "description": "Whether the listing is closed source (deployers cannot view or download the Truss, and forks copy mirrored weights instead of re-mirroring from upstream)", + "title": "Closed Source", + "type": "boolean" + }, "created_at": { "description": "Time the listing was created in ISO 8601 format", "format": "date-time", @@ -13703,6 +16986,7 @@ "display_name", "user_defined_id", "is_public", + "closed_source", "created_at", "modified_at" ], @@ -13744,6 +17028,12 @@ "description": "Whether the listing is publicly accessible", "title": "Is Public", "type": "boolean" + }, + "closed_source": { + "default": false, + "description": "Whether the listing is closed source (deployers cannot view or download the Truss, and forks copy mirrored weights instead of re-mirroring from upstream)", + "title": "Closed Source", + "type": "boolean" } }, "required": [ @@ -13904,6 +17194,12 @@ "title": "Allow Truss Download", "type": "boolean" }, + "closed_source": { + "default": false, + "description": "Whether the listing is closed source (deployers cannot view or download the Truss, and forks copy mirrored weights instead of re-mirroring from upstream). Only used when creating a new listing.", + "title": "Closed Source", + "type": "boolean" + }, "version_tag": { "description": "Human-readable tag for this version", "title": "Version Tag", @@ -14114,6 +17410,32 @@ "description": "Subtotal cost incurred on this date in dollars", "title": "Subtotal" }, + "compute_cost": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Compute cost incurred on this date in dollars", + "title": "Compute Cost" + }, + "surcharge_cost": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Model distribution surcharge incurred on this date in dollars", + "title": "Surcharge Cost" + }, "minutes": { "description": "Minutes used on this date", "title": "Minutes", @@ -14128,6 +17450,8 @@ "required": [ "date", "subtotal", + "compute_cost", + "surcharge_cost", "minutes", "inference_requests" ], @@ -14152,43 +17476,278 @@ "type": "string" } ], - "description": "Subtotal cost incurred on this date in dollars", + "description": "Subtotal cost incurred on this date in dollars", + "title": "Subtotal" + }, + "input_tokens": { + "description": "Number of input tokens on this date", + "title": "Input Tokens", + "type": "integer" + }, + "output_tokens": { + "description": "Number of output tokens on this date", + "title": "Output Tokens", + "type": "integer" + }, + "cached_input_tokens": { + "description": "Number of cached input tokens on this date", + "title": "Cached Input Tokens", + "type": "integer" + } + }, + "required": [ + "date", + "subtotal", + "input_tokens", + "output_tokens", + "cached_input_tokens" + ], + "title": "DailyModelApiUsageV1", + "type": "object" + }, + "DailyTrainingUsageV1": { + "properties": { + "date": { + "description": "Date of the usage", + "format": "date", + "title": "Date", + "type": "string" + }, + "subtotal": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Subtotal cost incurred on this date in dollars", + "title": "Subtotal" + }, + "minutes": { + "description": "Minutes used on this date", + "title": "Minutes", + "type": "integer" + } + }, + "required": [ + "date", + "subtotal", + "minutes" + ], + "title": "DailyTrainingUsageV1", + "type": "object" + }, + "DedicatedItemV1": { + "properties": { + "billable_resource": { + "$ref": "#/components/schemas/BillableResourceV1", + "description": "The model deployment resource" + }, + "subtotal": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Subtotal cost in dollars for this billable resource", + "title": "Subtotal" + }, + "compute_cost": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Compute cost in dollars for this billable resource", + "title": "Compute Cost" + }, + "surcharge_cost": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Model distribution surcharge in dollars for this billable resource", + "title": "Surcharge Cost" + }, + "minutes": { + "description": "Total minutes used for this billable resource", + "title": "Minutes", + "type": "integer" + }, + "inference_requests": { + "description": "Total inference requests for this billable resource", + "title": "Inference Requests", + "type": "integer" + }, + "daily": { + "description": "Daily usage breakdown", + "items": { + "$ref": "#/components/schemas/DailyDedicatedUsageV1" + }, + "title": "Daily", + "type": "array" + } + }, + "required": [ + "billable_resource", + "subtotal", + "compute_cost", + "surcharge_cost", + "minutes", + "inference_requests" + ], + "title": "DedicatedItemV1", + "type": "object" + }, + "DedicatedUsageV1": { + "properties": { + "subtotal": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Subtotal cost in dollars after applying credits used", + "title": "Subtotal" + }, + "credits_used": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Credits applied in dollars", + "title": "Credits Used" + }, + "total": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Total cost in dollars", + "title": "Total" + }, + "minutes": { + "description": "Total minutes used", + "title": "Minutes", + "type": "integer" + }, + "breakdown": { + "description": "Per-deployment usage breakdown", + "items": { + "$ref": "#/components/schemas/DedicatedItemV1" + }, + "title": "Breakdown", + "type": "array" + } + }, + "required": [ + "subtotal", + "credits_used", + "total", + "minutes" + ], + "title": "DedicatedUsageV1", + "type": "object" + }, + "ModelApiItemV1": { + "properties": { + "model_name": { + "description": "Model name", + "title": "Model Name", + "type": "string" + }, + "model_family": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Model family (e.g., llama, mistral)", + "title": "Model Family" + }, + "subtotal": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Subtotal cost in dollars for this model", "title": "Subtotal" }, "input_tokens": { - "description": "Number of input tokens on this date", + "description": "Total input tokens for this model", "title": "Input Tokens", "type": "integer" }, "output_tokens": { - "description": "Number of output tokens on this date", + "description": "Total output tokens for this model", "title": "Output Tokens", "type": "integer" }, "cached_input_tokens": { - "description": "Number of cached input tokens on this date", + "description": "Total cached input tokens for this model", "title": "Cached Input Tokens", "type": "integer" + }, + "daily": { + "description": "Daily usage breakdown", + "items": { + "$ref": "#/components/schemas/DailyModelApiUsageV1" + }, + "title": "Daily", + "type": "array" } }, "required": [ - "date", + "model_name", "subtotal", "input_tokens", "output_tokens", "cached_input_tokens" ], - "title": "DailyModelApiUsageV1", + "title": "ModelApiItemV1", "type": "object" }, - "DailyTrainingUsageV1": { + "ModelApisUsageV1": { "properties": { - "date": { - "description": "Date of the usage", - "format": "date", - "title": "Date", - "type": "string" - }, "subtotal": { "anyOf": [ { @@ -14199,28 +17758,66 @@ "type": "string" } ], - "description": "Subtotal cost incurred on this date in dollars", + "description": "Subtotal cost in dollars after applying credits used", "title": "Subtotal" }, - "minutes": { - "description": "Minutes used on this date", - "title": "Minutes", - "type": "integer" + "credits_used": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Credits applied in dollars", + "title": "Credits Used" + }, + "total": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Total cost in dollars", + "title": "Total" + }, + "breakdown": { + "description": "Per-model usage breakdown", + "items": { + "$ref": "#/components/schemas/ModelApiItemV1" + }, + "title": "Breakdown", + "type": "array" } }, "required": [ - "date", "subtotal", - "minutes" + "credits_used", + "total" ], - "title": "DailyTrainingUsageV1", + "title": "ModelApisUsageV1", "type": "object" }, - "DedicatedItemV1": { + "ResourceKind": { + "enum": [ + "MODEL_DEPLOYMENT", + "TRAINING_JOB", + "CHAINLET" + ], + "title": "ResourceKind", + "type": "string" + }, + "TrainingItemV1": { "properties": { "billable_resource": { "$ref": "#/components/schemas/BillableResourceV1", - "description": "The model deployment resource" + "description": "The training job resource" }, "subtotal": { "anyOf": [ @@ -14240,15 +17837,10 @@ "title": "Minutes", "type": "integer" }, - "inference_requests": { - "description": "Total inference requests for this billable resource", - "title": "Inference Requests", - "type": "integer" - }, "daily": { "description": "Daily usage breakdown", "items": { - "$ref": "#/components/schemas/DailyDedicatedUsageV1" + "$ref": "#/components/schemas/DailyTrainingUsageV1" }, "title": "Daily", "type": "array" @@ -14257,13 +17849,12 @@ "required": [ "billable_resource", "subtotal", - "minutes", - "inference_requests" + "minutes" ], - "title": "DedicatedItemV1", + "title": "TrainingItemV1", "type": "object" }, - "DedicatedUsageV1": { + "TrainingUsageV1": { "properties": { "subtotal": { "anyOf": [ @@ -14310,9 +17901,9 @@ "type": "integer" }, "breakdown": { - "description": "Per-deployment usage breakdown", + "description": "Per-job usage breakdown", "items": { - "$ref": "#/components/schemas/DedicatedItemV1" + "$ref": "#/components/schemas/TrainingItemV1" }, "title": "Breakdown", "type": "array" @@ -14324,17 +17915,155 @@ "total", "minutes" ], - "title": "DedicatedUsageV1", + "title": "TrainingUsageV1", + "type": "object" + }, + "UsageSummaryV1": { + "description": "Billing usage summary for the requested date range.", + "properties": { + "dedicated_usage": { + "anyOf": [ + { + "$ref": "#/components/schemas/DedicatedUsageV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Dedicated model serving usage" + }, + "training_usage": { + "anyOf": [ + { + "$ref": "#/components/schemas/TrainingUsageV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Training usage" + }, + "model_apis_usage": { + "anyOf": [ + { + "$ref": "#/components/schemas/ModelApisUsageV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Model APIs usage" + } + }, + "title": "UsageSummaryV1", + "type": "object" + }, + "UsageSummaryRequestV1": { + "properties": { + "start_date": { + "description": "Start date (ISO 8601, UTC). Earliest queryable: 2026-01-01.", + "format": "date-time", + "title": "Start Date", + "type": "string" + }, + "end_date": { + "description": "End date in ISO 8601 format (UTC). Date range cannot exceed 31 days.", + "format": "date-time", + "title": "End Date", + "type": "string" + } + }, + "required": [ + "start_date", + "end_date" + ], + "title": "UsageSummaryRequestV1", + "type": "object" + }, + "UserInfoV1": { + "description": "A Baseten user.", + "properties": { + "user_id": { + "description": "Unique identifier for the user", + "title": "User Id", + "type": "string" + }, + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Email address of the user", + "title": "Email" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Display name of the user", + "title": "Name" + }, + "workspace_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Name of the user's workspace", + "title": "Workspace Name" + } + }, + "required": [ + "user_id" + ], + "title": "UserInfoV1", + "type": "object" + }, + "UsersResponseV1": { + "description": "A page of users in the caller's workspace.", + "properties": { + "items": { + "description": "Items in this page.", + "items": { + "$ref": "#/components/schemas/UserInfoV1" + }, + "title": "Items", + "type": "array" + }, + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." + } + }, + "required": [ + "items", + "pagination" + ], + "title": "UsersResponseV1", "type": "object" }, - "ModelApiItemV1": { + "UsersRequestV1": { + "description": "Request parameters for listing users.", "properties": { - "model_name": { - "description": "Model name", - "title": "Model Name", - "type": "string" - }, - "model_family": { + "cursor": { "anyOf": [ { "type": "string" @@ -14344,345 +18073,416 @@ } ], "default": null, - "description": "Model family (e.g., llama, mistral)", - "title": "Model Family" + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "title": "Cursor" }, - "subtotal": { + "limit": { + "default": 100, + "description": "Maximum number of items to return.", + "maximum": 1000, + "minimum": 1, + "title": "Limit", + "type": "integer" + }, + "email": { "anyOf": [ { - "type": "number" + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Subtotal cost in dollars for this model", - "title": "Subtotal" - }, - "input_tokens": { - "description": "Total input tokens for this model", - "title": "Input Tokens", - "type": "integer" - }, - "output_tokens": { - "description": "Total output tokens for this model", - "title": "Output Tokens", - "type": "integer" - }, - "cached_input_tokens": { - "description": "Total cached input tokens for this model", - "title": "Cached Input Tokens", - "type": "integer" - }, - "daily": { - "description": "Daily usage breakdown", - "items": { - "$ref": "#/components/schemas/DailyModelApiUsageV1" - }, - "title": "Daily", - "type": "array" + "default": null, + "description": "When set, returns only users with this exact email, if any.", + "title": "Email" } }, - "required": [ - "model_name", - "subtotal", - "input_tokens", - "output_tokens", - "cached_input_tokens" - ], - "title": "ModelApiItemV1", + "title": "UsersRequestV1", "type": "object" }, - "ModelApisUsageV1": { + "EndpointTargetV1": { + "description": "One configured upstream target of an endpoint.", "properties": { - "subtotal": { + "provider": { + "$ref": "#/components/schemas/GatewayProvider", + "description": "Upstream provider." + }, + "secret_id": { "anyOf": [ { - "type": "number" + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Subtotal cost in dollars after applying credits used", - "title": "Subtotal" + "default": null, + "description": "Referenced secret, if any.", + "title": "Secret Id" }, - "credits_used": { + "target_model": { "anyOf": [ { - "type": "number" + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "null" + } + ], + "default": null, + "description": "Upstream model name, if any.", + "title": "Target Model" + }, + "base_url": { + "anyOf": [ + { "type": "string" + }, + { + "type": "null" } ], - "description": "Credits applied in dollars", - "title": "Credits Used" + "default": null, + "description": "Custom OpenAI-compatible base URL, if any.", + "title": "Base Url" }, - "total": { + "model_id": { "anyOf": [ { - "type": "number" + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "null" + } + ], + "default": null, + "description": "Baseten model, if any.", + "title": "Model Id" + }, + "environment_name": { + "anyOf": [ + { "type": "string" + }, + { + "type": "null" } ], - "description": "Total cost in dollars", - "title": "Total" + "default": null, + "description": "Baseten model environment, if non-production.", + "title": "Environment Name" + } + }, + "required": [ + "provider" + ], + "title": "EndpointTargetV1", + "type": "object" + }, + "EndpointV1": { + "description": "A Gateway endpoint: a slug and its priority-ordered targets (index 0 tried first).", + "properties": { + "id": { + "description": "Stable identifier for the endpoint.", + "title": "Id", + "type": "string" }, - "breakdown": { - "description": "Per-model usage breakdown", + "slug": { + "description": "Globally-unique routing slug.", + "examples": [ + "baseten/mymodel-4" + ], + "title": "Slug", + "type": "string" + }, + "created_at": { + "description": "Creation time, ISO 8601.", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "updated_at": { + "description": "Last update time, ISO 8601.", + "format": "date-time", + "title": "Updated At", + "type": "string" + }, + "targets": { + "description": "The endpoint's upstream targets. Exactly one target is supported at this time.", "items": { - "$ref": "#/components/schemas/ModelApiItemV1" + "$ref": "#/components/schemas/EndpointTargetV1" }, - "title": "Breakdown", + "title": "Targets", "type": "array" } }, "required": [ - "subtotal", - "credits_used", - "total" + "id", + "slug", + "created_at", + "updated_at", + "targets" ], - "title": "ModelApisUsageV1", + "title": "EndpointV1", "type": "object" }, - "ResourceKind": { + "GatewayProvider": { + "description": "Customer-facing provider for an endpoint target.\n\nExternal providers resolve to a fixed upstream host + protocol adapter via\n``external_provider_configs()``; ``BASETEN`` derives its host from the referenced oracle.", "enum": [ - "MODEL_DEPLOYMENT", - "TRAINING_JOB", - "CHAINLET" - ], - "title": "ResourceKind", + "ANTHROPIC", + "OPENAI", + "BASETEN", + "BASETEN_MODEL_API", + "VERTEX", + "OPENAI_COMPATIBLE" + ], + "title": "GatewayProvider", "type": "string" }, - "TrainingItemV1": { + "EndpointsResponseV1": { "properties": { - "billable_resource": { - "$ref": "#/components/schemas/BillableResourceV1", - "description": "The training job resource" - }, - "subtotal": { - "anyOf": [ - { - "type": "number" - }, - { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" - } - ], - "description": "Subtotal cost in dollars for this billable resource", - "title": "Subtotal" - }, - "minutes": { - "description": "Total minutes used for this billable resource", - "title": "Minutes", - "type": "integer" - }, - "daily": { - "description": "Daily usage breakdown", + "items": { + "description": "Items in this page.", "items": { - "$ref": "#/components/schemas/DailyTrainingUsageV1" + "$ref": "#/components/schemas/EndpointV1" }, - "title": "Daily", + "title": "Items", "type": "array" + }, + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." } }, "required": [ - "billable_resource", - "subtotal", - "minutes" + "items", + "pagination" ], - "title": "TrainingItemV1", + "title": "EndpointsResponseV1", "type": "object" }, - "TrainingUsageV1": { + "EndpointTargetRequestV1": { + "description": "One desired upstream target. The customer picks a provider; Baseten owns the\nupstream host and protocol adapter.", "properties": { - "subtotal": { - "anyOf": [ - { - "type": "number" - }, - { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" - } - ], - "description": "Subtotal cost in dollars after applying credits used", - "title": "Subtotal" + "provider": { + "$ref": "#/components/schemas/GatewayProvider", + "description": "Upstream provider for this target.", + "examples": [ + "ANTHROPIC", + "OPENAI", + "OPENAI_COMPATIBLE", + "BASETEN" + ] }, - "credits_used": { + "secret_id": { "anyOf": [ { - "type": "number" + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Credits applied in dollars", - "title": "Credits Used" + "default": null, + "description": "Secret holding the provider credential. Required for external providers.", + "examples": [ + "3kZ9xqd" + ], + "title": "Secret Id" }, - "total": { + "target_model": { "anyOf": [ { - "type": "number" + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Total cost in dollars", - "title": "Total" - }, - "minutes": { - "description": "Total minutes used", - "title": "Minutes", - "type": "integer" - }, - "breakdown": { - "description": "Per-job usage breakdown", - "items": { - "$ref": "#/components/schemas/TrainingItemV1" - }, - "title": "Breakdown", - "type": "array" - } - }, - "required": [ - "subtotal", - "credits_used", - "total", - "minutes" - ], - "title": "TrainingUsageV1", - "type": "object" - }, - "UsageSummaryV1": { - "description": "Billing usage summary for the requested date range.", - "properties": { - "dedicated_usage": { + "default": null, + "description": "Model name to send upstream. Required for external providers and optional for BASETEN targets.", + "examples": [ + "gpt-4o" + ], + "title": "Target Model" + }, + "base_url": { "anyOf": [ { - "$ref": "#/components/schemas/DedicatedUsageV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Dedicated model serving usage" + "description": "HTTPS base URL of the upstream OpenAI-compatible server. Must not include a port. Required for and only valid with OPENAI_COMPATIBLE.", + "examples": [ + "https://my-vllm.example.com" + ], + "title": "Base Url" }, - "training_usage": { + "model_id": { "anyOf": [ { - "$ref": "#/components/schemas/TrainingUsageV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Training usage" + "description": "Baseten model to route to. Required for and only valid with BASETEN.", + "examples": [ + "3kZ9xqd" + ], + "title": "Model Id" }, - "model_apis_usage": { + "environment_name": { "anyOf": [ { - "$ref": "#/components/schemas/ModelApisUsageV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Model APIs usage" + "description": "Baseten model environment to route to. Only valid with BASETEN. Omit or pass `production` to target production.", + "examples": [ + "staging" + ], + "title": "Environment Name" } }, - "title": "UsageSummaryV1", + "required": [ + "provider" + ], + "title": "EndpointTargetRequestV1", "type": "object" }, - "UsageSummaryRequestV1": { + "CreateEndpointRequestV1": { "properties": { - "start_date": { - "description": "Start date (ISO 8601, UTC). Earliest queryable: 2026-01-01.", - "format": "date-time", - "title": "Start Date", + "slug": { + "description": "Globally-unique slug of the form '{org_prefix}/{name}'.", + "examples": [ + "baseten/mymodel-4" + ], + "title": "Slug", "type": "string" }, - "end_date": { - "description": "End date in ISO 8601 format (UTC). Date range cannot exceed 31 days.", - "format": "date-time", - "title": "End Date", - "type": "string" + "targets": { + "description": "The endpoint's upstream targets. Exactly one target is supported at this time.", + "examples": [ + [ + { + "environment_name": "staging", + "model_id": "3kZ9xqd", + "provider": "BASETEN", + "target_model": "custom/model-name" + } + ], + [ + { + "provider": "OPENAI", + "secret_id": "3kZ9xqd", + "target_model": "gpt-4o" + } + ], + [ + { + "base_url": "https://my-vllm.example.com", + "provider": "OPENAI_COMPATIBLE", + "secret_id": "3kZ9xqd", + "target_model": "my-model" + } + ] + ], + "items": { + "$ref": "#/components/schemas/EndpointTargetRequestV1" + }, + "maxItems": 1, + "minItems": 1, + "title": "Targets", + "type": "array" } }, "required": [ - "start_date", - "end_date" + "slug", + "targets" ], - "title": "UsageSummaryRequestV1", + "title": "CreateEndpointRequestV1", "type": "object" }, - "UserInfoV1": { - "description": "A Baseten user.", + "EndpointTombstoneV1": { "properties": { - "user_id": { - "description": "Unique identifier for the user", - "title": "User Id", + "id": { + "description": "Identifier of the deleted endpoint.", + "title": "Id", "type": "string" }, - "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Email address of the user", - "title": "Email" - }, - "name": { + "slug": { + "description": "Slug of the deleted endpoint.", + "title": "Slug", + "type": "string" + } + }, + "required": [ + "id", + "slug" + ], + "title": "EndpointTombstoneV1", + "type": "object" + }, + "UpdateEndpointRequestV1": { + "description": "PATCH body. Replaces the endpoint's full target list. The slug is immutable\nafter creation; to change it, create a new endpoint and delete this one.", + "properties": { + "targets": { "anyOf": [ { - "type": "string" + "items": { + "$ref": "#/components/schemas/EndpointTargetRequestV1" + }, + "maxItems": 1, + "minItems": 1, + "type": "array" }, { "type": "null" } ], "default": null, - "description": "Display name of the user", - "title": "Name" - }, - "workspace_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "description": "The endpoint's upstream targets. Exactly one target is supported at this time.", + "examples": [ + [ + { + "environment_name": "staging", + "model_id": "3kZ9xqd", + "provider": "BASETEN", + "target_model": "custom/model-name" + } + ], + [ + { + "provider": "OPENAI", + "secret_id": "3kZ9xqd", + "target_model": "gpt-4o" + } + ], + [ + { + "base_url": "https://my-vllm.example.com", + "provider": "OPENAI_COMPATIBLE", + "secret_id": "3kZ9xqd", + "target_model": "my-model" + } + ] ], - "default": null, - "description": "Name of the user's workspace", - "title": "Workspace Name" + "title": "Targets" } }, - "required": [ - "user_id" - ], - "title": "UserInfoV1", + "title": "UpdateEndpointRequestV1", "type": "object" }, "EffectiveModelConfigV1": { @@ -14737,7 +18537,7 @@ 1000, 50000 ], - "minimum": 1, + "minimum": 0, "title": "Threshold", "type": "integer" }, @@ -14781,7 +18581,7 @@ "examples": [ 10000000 ], - "minimum": 1, + "minimum": 0, "title": "Threshold", "type": "integer" }, @@ -14921,14 +18721,6 @@ "title": "LimitEnforcementV1", "type": "string" }, - "LimitTypeV1": { - "enum": [ - "REQUEST", - "TOKEN" - ], - "title": "LimitTypeV1", - "type": "string" - }, "ModelConfigV1": { "properties": { "slug": { @@ -14957,78 +18749,6 @@ "title": "ModelConfigV1", "type": "object" }, - "PaginationResponseV1": { - "properties": { - "has_more": { - "description": "Whether more items exist after this page.", - "title": "Has More", - "type": "boolean" - }, - "cursor": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Opaque cursor to pass into the next request. Null when there is no next page.", - "title": "Cursor" - } - }, - "required": [ - "has_more" - ], - "title": "PaginationResponseV1", - "type": "object" - }, - "RateLimitUnitV1": { - "enum": [ - "SECOND", - "MINUTE" - ], - "title": "RateLimitUnitV1", - "type": "string" - }, - "RateLimitV1": { - "properties": { - "type": { - "$ref": "#/components/schemas/LimitTypeV1", - "description": "The type of the rate limit", - "examples": [ - "TOKEN", - "REQUEST" - ] - }, - "unit": { - "$ref": "#/components/schemas/RateLimitUnitV1", - "description": "The unit of the rate limit", - "examples": [ - "SECOND", - "MINUTE" - ] - }, - "threshold": { - "description": "The threshold for the rate limit", - "examples": [ - 1000, - 50000 - ], - "minimum": 1, - "title": "Threshold", - "type": "integer" - } - }, - "required": [ - "type", - "unit", - "threshold" - ], - "title": "RateLimitV1", - "type": "object" - }, "UsageLimitUnitV1": { "enum": [ "DAY" @@ -15058,7 +18778,7 @@ "examples": [ 10000000 ], - "minimum": 1, + "minimum": 0, "title": "Threshold", "type": "integer" } @@ -15104,6 +18824,7 @@ "items": { "$ref": "#/components/schemas/ModelConfigV1" }, + "minItems": 1, "title": "Models", "type": "array" }, @@ -15352,35 +19073,35 @@ "in": "path", "required": true }, - "model_id": { + "env_name": { "schema": { "type": "string" }, - "name": "model_id", + "name": "env_name", "in": "path", "required": true }, - "deployment_id": { + "model_id": { "schema": { "type": "string" }, - "name": "deployment_id", + "name": "model_id", "in": "path", "required": true }, - "replica_id": { + "deployment_id": { "schema": { "type": "string" }, - "name": "replica_id", + "name": "deployment_id", "in": "path", "required": true }, - "env_name": { + "replica_id": { "schema": { "type": "string" }, - "name": "env_name", + "name": "replica_id", "in": "path", "required": true }, @@ -15432,43 +19153,43 @@ "in": "path", "required": true }, - "trainer_id": { + "run_id": { "schema": { "type": "string" }, - "name": "trainer_id", + "name": "run_id", "in": "path", "required": true }, - "checkpoint_id": { + "sampler_id": { "schema": { "type": "string" }, - "name": "checkpoint_id", + "name": "sampler_id", "in": "path", "required": true }, - "run_id": { + "checkpoint_id": { "schema": { "type": "string" }, - "name": "run_id", + "name": "checkpoint_id", "in": "path", "required": true }, - "sampler_id": { + "api_key_prefix": { "schema": { "type": "string" }, - "name": "sampler_id", + "name": "api_key_prefix", "in": "path", "required": true }, - "api_key_prefix": { + "model_api_name": { "schema": { "type": "string" }, - "name": "api_key_prefix", + "name": "model_api_name", "in": "path", "required": true }, @@ -15496,6 +19217,14 @@ "in": "path", "required": true }, + "endpoint_id": { + "schema": { + "type": "string" + }, + "name": "endpoint_id", + "in": "path", + "required": true + }, "group_id": { "schema": { "type": "string" @@ -15506,11 +19235,10 @@ } }, "securitySchemes": { - "ApiKeyAuth": { - "type": "apiKey", - "in": "header", - "name": "Authorization", - "description": "You must specify the scheme 'Api-Key' in the Authorization header. For example, `Authorization: Api-Key `" + "BearerAuth": { + "type": "http", + "scheme": "bearer", + "description": "Send `Authorization: Bearer `. The legacy `Authorization: Api-Key ` scheme is also accepted." } } } diff --git a/tests/client/test_management.py b/tests/client/test_management.py index ee9b390..63f1b8d 100644 --- a/tests/client/test_management.py +++ b/tests/client/test_management.py @@ -20,6 +20,7 @@ } MINIMAL_SECRET = { + "id": "sec123", "name": "MY_SECRET", "created_at": "2024-01-01T00:00:00Z", "team_name": "my-team", diff --git a/uv.lock b/uv.lock index f38fb37..6d556a4 100644 --- a/uv.lock +++ b/uv.lock @@ -96,7 +96,7 @@ wheels = [ [[package]] name = "baseten" -version = "0.9.0" +version = "0.9.1" source = { editable = "." } dependencies = [ { name = "httpx" }, From 9577cca391709b72c231a3456d09024b6b8edfd0 Mon Sep 17 00:00:00 2001 From: Chad Retz Date: Tue, 14 Jul 2026 14:07:44 -0500 Subject: [PATCH 2/2] Generate query parameter support and rename request kwarg --- baseten/client/inferenceapi/_client.py | 267 ++++-- baseten/client/managementapi/__init__.py | 38 + baseten/client/managementapi/_client.py | 1082 ++++++++++++++++------ baseten/client/managementapi/_models.py | 672 ++++++++++++-- pyproject.toml | 2 +- scripts/apigen/clientgen.py | 123 ++- scripts/apigen/preprocess.py | 57 ++ tests/client/test_inference.py | 10 +- tests/client/test_management.py | 28 +- tests/test_e2e.py | 4 +- uv.lock | 2 +- 11 files changed, 1833 insertions(+), 452 deletions(-) diff --git a/baseten/client/inferenceapi/_client.py b/baseten/client/inferenceapi/_client.py index 1974bcc..d946141 100644 --- a/baseten/client/inferenceapi/_client.py +++ b/baseten/client/inferenceapi/_client.py @@ -56,6 +56,7 @@ class _ApiRequest: path_fmt: str path_args: list[str] body: Any + query: Any success_code: int error_codes: dict[int, str] | None @@ -73,7 +74,7 @@ def __init__(self, http_client: httpx.Client) -> None: self._http_client = http_client def async_predict( - self, *, env_name: str, body: AsyncPredictRequest + self, *, env_name: str, request: AsyncPredictRequest ) -> AsyncPredictOutput: """Asynchronously call a named environment of a model.""" return self._do_json( @@ -82,7 +83,8 @@ def async_predict( method="POST", path_fmt="/environments/{}/async_predict", path_args=[env_name], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -95,7 +97,7 @@ def async_predict( ) def async_predict_deployment( - self, *, deployment_id: str, body: AsyncPredictRequest + self, *, deployment_id: str, request: AsyncPredictRequest ) -> AsyncPredictOutput: """Asynchronously call a specific deployment of a model.""" return self._do_json( @@ -104,7 +106,8 @@ def async_predict_deployment( method="POST", path_fmt="/deployment/{}/async_predict", path_args=[deployment_id], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -117,7 +120,7 @@ def async_predict_deployment( ) def async_predict_development( - self, *, body: AsyncPredictRequest + self, *, request: AsyncPredictRequest ) -> AsyncPredictOutput: """Asynchronously call the development deployment of a model.""" return self._do_json( @@ -126,7 +129,8 @@ def async_predict_development( method="POST", path_fmt="/development/async_predict", path_args=[], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -139,7 +143,7 @@ def async_predict_development( ) def async_predict_production( - self, *, body: AsyncPredictRequest + self, *, request: AsyncPredictRequest ) -> AsyncPredictOutput: """Asynchronously call the production environment of a model.""" return self._do_json( @@ -148,7 +152,8 @@ def async_predict_production( method="POST", path_fmt="/production/async_predict", path_args=[], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -161,7 +166,7 @@ def async_predict_production( ) def async_predict_regional( - self, *, body: AsyncPredictRequest + self, *, request: AsyncPredictRequest ) -> AsyncPredictOutput: """Asynchronously call a regional environment of a model.""" return self._do_json( @@ -170,7 +175,8 @@ def async_predict_regional( method="POST", path_fmt="/async_predict", path_args=[], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -183,7 +189,7 @@ def async_predict_regional( ) def async_run_remote( - self, *, env_name: str, body: AsyncRunRemoteInput + self, *, env_name: str, request: AsyncRunRemoteInput ) -> AsyncRunRemoteOutput: """Asynchronously call a named environment of a chain.""" return self._do_json( @@ -192,7 +198,8 @@ def async_run_remote( method="POST", path_fmt="/environments/{}/async_run_remote", path_args=[env_name], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -204,7 +211,7 @@ def async_run_remote( ) def async_run_remote_deployment( - self, *, deployment_id: str, body: AsyncRunRemoteInput + self, *, deployment_id: str, request: AsyncRunRemoteInput ) -> AsyncRunRemoteOutput: """Asynchronously call a specific deployment of a chain.""" return self._do_json( @@ -213,7 +220,8 @@ def async_run_remote_deployment( method="POST", path_fmt="/deployment/{}/async_run_remote", path_args=[deployment_id], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -225,7 +233,7 @@ def async_run_remote_deployment( ) def async_run_remote_development( - self, *, body: AsyncRunRemoteInput + self, *, request: AsyncRunRemoteInput ) -> AsyncRunRemoteOutput: """Asynchronously call the development deployment of a chain.""" return self._do_json( @@ -234,7 +242,8 @@ def async_run_remote_development( method="POST", path_fmt="/development/async_run_remote", path_args=[], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -246,7 +255,7 @@ def async_run_remote_development( ) def async_run_remote_production( - self, *, body: AsyncRunRemoteInput + self, *, request: AsyncRunRemoteInput ) -> AsyncRunRemoteOutput: """Asynchronously call the production environment of a chain.""" return self._do_json( @@ -255,7 +264,8 @@ def async_run_remote_production( method="POST", path_fmt="/production/async_run_remote", path_args=[], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -267,7 +277,7 @@ def async_run_remote_production( ) def async_run_remote_regional( - self, *, body: AsyncRunRemoteInput + self, *, request: AsyncRunRemoteInput ) -> AsyncRunRemoteOutput: """Asynchronously call a regional environment of a chain.""" return self._do_json( @@ -276,7 +286,8 @@ def async_run_remote_regional( method="POST", path_fmt="/async_run_remote", path_args=[], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -296,6 +307,7 @@ def cancel_async_request(self, *, request_id: str) -> CancelAsyncRequestOutput: path_fmt="/async_request/{}", path_args=[request_id], body=None, + query=None, success_code=200, error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), @@ -310,6 +322,7 @@ def get_async_queue_status(self, *, env_name: str) -> GetAsyncQueueStatusOutput: path_fmt="/environments/{}/async_queue_status", path_args=[env_name], body=None, + query=None, success_code=200, error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), @@ -326,6 +339,7 @@ def get_async_queue_status_deployment( path_fmt="/deployment/{}/async_queue_status", path_args=[deployment_id], body=None, + query=None, success_code=200, error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), @@ -340,6 +354,7 @@ def get_async_queue_status_development(self) -> GetAsyncQueueStatusOutput: path_fmt="/development/async_queue_status", path_args=[], body=None, + query=None, success_code=200, error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), @@ -354,6 +369,7 @@ def get_async_queue_status_production(self) -> GetAsyncQueueStatusOutput: path_fmt="/production/async_queue_status", path_args=[], body=None, + query=None, success_code=200, error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), @@ -368,6 +384,7 @@ def get_async_queue_status_regional(self) -> GetAsyncQueueStatusOutput: path_fmt="/async_queue_status", path_args=[], body=None, + query=None, success_code=200, error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), @@ -384,12 +401,13 @@ def get_async_request_status( path_fmt="/async_request/{}", path_args=[request_id], body=None, + query=None, success_code=200, error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), ) - def predict(self, *, env_name: str, body: PredictInput) -> PredictOutput: + def predict(self, *, env_name: str, request: PredictInput) -> PredictOutput: """Call the model deployment associated with a specified environment.""" return self._do_json( PredictOutput, @@ -397,7 +415,8 @@ def predict(self, *, env_name: str, body: PredictInput) -> PredictOutput: method="POST", path_fmt="/environments/{}/predict", path_args=[env_name], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -411,7 +430,7 @@ def predict(self, *, env_name: str, body: PredictInput) -> PredictOutput: ) def predict_deployment( - self, *, deployment_id: str, body: PredictInput + self, *, deployment_id: str, request: PredictInput ) -> PredictOutput: """Call a specific deployment of a model by deployment ID.""" return self._do_json( @@ -420,7 +439,8 @@ def predict_deployment( method="POST", path_fmt="/deployment/{}/predict", path_args=[deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -433,7 +453,7 @@ def predict_deployment( ), ) - def predict_development(self, *, body: PredictInput) -> PredictOutput: + def predict_development(self, *, request: PredictInput) -> PredictOutput: """Call the development deployment of a model.""" return self._do_json( PredictOutput, @@ -441,7 +461,8 @@ def predict_development(self, *, body: PredictInput) -> PredictOutput: method="POST", path_fmt="/development/predict", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -454,7 +475,7 @@ def predict_development(self, *, body: PredictInput) -> PredictOutput: ), ) - def predict_production(self, *, body: PredictInput) -> PredictOutput: + def predict_production(self, *, request: PredictInput) -> PredictOutput: """Call the production environment of a model.""" return self._do_json( PredictOutput, @@ -462,7 +483,8 @@ def predict_production(self, *, body: PredictInput) -> PredictOutput: method="POST", path_fmt="/production/predict", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -475,7 +497,7 @@ def predict_production(self, *, body: PredictInput) -> PredictOutput: ), ) - def predict_regional(self, *, body: PredictInput) -> PredictOutput: + def predict_regional(self, *, request: PredictInput) -> PredictOutput: """Call a regional environment of a model.""" return self._do_json( PredictOutput, @@ -483,7 +505,8 @@ def predict_regional(self, *, body: PredictInput) -> PredictOutput: method="POST", path_fmt="/predict", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -496,7 +519,7 @@ def predict_regional(self, *, body: PredictInput) -> PredictOutput: ), ) - def run_remote(self, *, env_name: str, body: RunRemoteInput) -> RunRemoteOutput: + def run_remote(self, *, env_name: str, request: RunRemoteInput) -> RunRemoteOutput: """Call the chain deployment associated with a specified environment.""" return self._do_json( RunRemoteOutput, @@ -504,7 +527,8 @@ def run_remote(self, *, env_name: str, body: RunRemoteInput) -> RunRemoteOutput: method="POST", path_fmt="/environments/{}/run_remote", path_args=[env_name], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -518,7 +542,7 @@ def run_remote(self, *, env_name: str, body: RunRemoteInput) -> RunRemoteOutput: ) def run_remote_deployment( - self, *, deployment_id: str, body: RunRemoteInput + self, *, deployment_id: str, request: RunRemoteInput ) -> RunRemoteOutput: """Call a specific chain deployment by deployment ID.""" return self._do_json( @@ -527,7 +551,8 @@ def run_remote_deployment( method="POST", path_fmt="/deployment/{}/run_remote", path_args=[deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -540,7 +565,7 @@ def run_remote_deployment( ), ) - def run_remote_development(self, *, body: RunRemoteInput) -> RunRemoteOutput: + def run_remote_development(self, *, request: RunRemoteInput) -> RunRemoteOutput: """Call the development deployment of a chain.""" return self._do_json( RunRemoteOutput, @@ -548,7 +573,8 @@ def run_remote_development(self, *, body: RunRemoteInput) -> RunRemoteOutput: method="POST", path_fmt="/development/run_remote", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -561,7 +587,7 @@ def run_remote_development(self, *, body: RunRemoteInput) -> RunRemoteOutput: ), ) - def run_remote_production(self, *, body: RunRemoteInput) -> RunRemoteOutput: + def run_remote_production(self, *, request: RunRemoteInput) -> RunRemoteOutput: """Call the production environment of a chain.""" return self._do_json( RunRemoteOutput, @@ -569,7 +595,8 @@ def run_remote_production(self, *, body: RunRemoteInput) -> RunRemoteOutput: method="POST", path_fmt="/production/run_remote", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -582,7 +609,7 @@ def run_remote_production(self, *, body: RunRemoteInput) -> RunRemoteOutput: ), ) - def run_remote_regional(self, *, body: RunRemoteInput) -> RunRemoteOutput: + def run_remote_regional(self, *, request: RunRemoteInput) -> RunRemoteOutput: """Call a regional environment of a chain.""" return self._do_json( RunRemoteOutput, @@ -590,7 +617,8 @@ def run_remote_regional(self, *, body: RunRemoteInput) -> RunRemoteOutput: method="POST", path_fmt="/run_remote", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -611,6 +639,7 @@ def wake(self, *, env_name: str) -> None: path_fmt="/environments/{}/wake", path_args=[env_name], body=None, + query=None, success_code=202, error_codes={401: "ErrorResponse"}, ) @@ -624,6 +653,7 @@ def wake_deployment(self, *, deployment_id: str) -> None: path_fmt="/deployment/{}/wake", path_args=[deployment_id], body=None, + query=None, success_code=202, error_codes={401: "ErrorResponse"}, ) @@ -637,6 +667,7 @@ def wake_development(self) -> None: path_fmt="/development/wake", path_args=[], body=None, + query=None, success_code=202, error_codes={401: "ErrorResponse"}, ) @@ -650,6 +681,7 @@ def wake_production(self) -> None: path_fmt="/production/wake", path_args=[], body=None, + query=None, success_code=202, error_codes={401: "ErrorResponse"}, ) @@ -663,6 +695,7 @@ def wake_regional(self) -> None: path_fmt="/wake", path_args=[], body=None, + query=None, success_code=202, error_codes={401: "ErrorResponse"}, ) @@ -675,10 +708,25 @@ def _do(self, request: _ApiRequest) -> httpx.Response: json_body = None if request.body is not None: if isinstance(request.body, BaseModel): - json_body = request.body.model_dump(mode="json") + # Only fields the caller set are sent, so unset fields fall + # back to the server default rather than being reset here. + # An explicit None is kept, since null can mean "clear". + json_body = request.body.model_dump(mode="json", exclude_unset=True) else: json_body = request.body - response = self._http_client.request(request.method, path, json=json_body) + params = None + if request.query is not None: + if isinstance(request.query, BaseModel): + # As above, plus dropping None: a null query parameter is + # meaningless and would otherwise serialize as an empty string. + params = request.query.model_dump( + mode="json", exclude_unset=True, exclude_none=True + ) + else: + params = request.query + response = self._http_client.request( + request.method, path, json=json_body, params=params + ) if response.status_code != request.success_code: if request.error_codes and response.status_code in request.error_codes: error_name = request.error_codes[response.status_code] @@ -723,7 +771,7 @@ def __init__(self, http_client: httpx.AsyncClient) -> None: self._http_client = http_client async def async_predict( - self, *, env_name: str, body: AsyncPredictRequest + self, *, env_name: str, request: AsyncPredictRequest ) -> AsyncPredictOutput: """Asynchronously call a named environment of a model.""" return await self._do_json( @@ -732,7 +780,8 @@ async def async_predict( method="POST", path_fmt="/environments/{}/async_predict", path_args=[env_name], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -745,7 +794,7 @@ async def async_predict( ) async def async_predict_deployment( - self, *, deployment_id: str, body: AsyncPredictRequest + self, *, deployment_id: str, request: AsyncPredictRequest ) -> AsyncPredictOutput: """Asynchronously call a specific deployment of a model.""" return await self._do_json( @@ -754,7 +803,8 @@ async def async_predict_deployment( method="POST", path_fmt="/deployment/{}/async_predict", path_args=[deployment_id], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -767,7 +817,7 @@ async def async_predict_deployment( ) async def async_predict_development( - self, *, body: AsyncPredictRequest + self, *, request: AsyncPredictRequest ) -> AsyncPredictOutput: """Asynchronously call the development deployment of a model.""" return await self._do_json( @@ -776,7 +826,8 @@ async def async_predict_development( method="POST", path_fmt="/development/async_predict", path_args=[], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -789,7 +840,7 @@ async def async_predict_development( ) async def async_predict_production( - self, *, body: AsyncPredictRequest + self, *, request: AsyncPredictRequest ) -> AsyncPredictOutput: """Asynchronously call the production environment of a model.""" return await self._do_json( @@ -798,7 +849,8 @@ async def async_predict_production( method="POST", path_fmt="/production/async_predict", path_args=[], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -811,7 +863,7 @@ async def async_predict_production( ) async def async_predict_regional( - self, *, body: AsyncPredictRequest + self, *, request: AsyncPredictRequest ) -> AsyncPredictOutput: """Asynchronously call a regional environment of a model.""" return await self._do_json( @@ -820,7 +872,8 @@ async def async_predict_regional( method="POST", path_fmt="/async_predict", path_args=[], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -833,7 +886,7 @@ async def async_predict_regional( ) async def async_run_remote( - self, *, env_name: str, body: AsyncRunRemoteInput + self, *, env_name: str, request: AsyncRunRemoteInput ) -> AsyncRunRemoteOutput: """Asynchronously call a named environment of a chain.""" return await self._do_json( @@ -842,7 +895,8 @@ async def async_run_remote( method="POST", path_fmt="/environments/{}/async_run_remote", path_args=[env_name], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -854,7 +908,7 @@ async def async_run_remote( ) async def async_run_remote_deployment( - self, *, deployment_id: str, body: AsyncRunRemoteInput + self, *, deployment_id: str, request: AsyncRunRemoteInput ) -> AsyncRunRemoteOutput: """Asynchronously call a specific deployment of a chain.""" return await self._do_json( @@ -863,7 +917,8 @@ async def async_run_remote_deployment( method="POST", path_fmt="/deployment/{}/async_run_remote", path_args=[deployment_id], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -875,7 +930,7 @@ async def async_run_remote_deployment( ) async def async_run_remote_development( - self, *, body: AsyncRunRemoteInput + self, *, request: AsyncRunRemoteInput ) -> AsyncRunRemoteOutput: """Asynchronously call the development deployment of a chain.""" return await self._do_json( @@ -884,7 +939,8 @@ async def async_run_remote_development( method="POST", path_fmt="/development/async_run_remote", path_args=[], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -896,7 +952,7 @@ async def async_run_remote_development( ) async def async_run_remote_production( - self, *, body: AsyncRunRemoteInput + self, *, request: AsyncRunRemoteInput ) -> AsyncRunRemoteOutput: """Asynchronously call the production environment of a chain.""" return await self._do_json( @@ -905,7 +961,8 @@ async def async_run_remote_production( method="POST", path_fmt="/production/async_run_remote", path_args=[], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -917,7 +974,7 @@ async def async_run_remote_production( ) async def async_run_remote_regional( - self, *, body: AsyncRunRemoteInput + self, *, request: AsyncRunRemoteInput ) -> AsyncRunRemoteOutput: """Asynchronously call a regional environment of a chain.""" return await self._do_json( @@ -926,7 +983,8 @@ async def async_run_remote_regional( method="POST", path_fmt="/async_run_remote", path_args=[], - body=body, + body=request, + query=None, success_code=201, error_codes={ 400: "ErrorResponse", @@ -948,6 +1006,7 @@ async def cancel_async_request( path_fmt="/async_request/{}", path_args=[request_id], body=None, + query=None, success_code=200, error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), @@ -964,6 +1023,7 @@ async def get_async_queue_status( path_fmt="/environments/{}/async_queue_status", path_args=[env_name], body=None, + query=None, success_code=200, error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), @@ -980,6 +1040,7 @@ async def get_async_queue_status_deployment( path_fmt="/deployment/{}/async_queue_status", path_args=[deployment_id], body=None, + query=None, success_code=200, error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), @@ -994,6 +1055,7 @@ async def get_async_queue_status_development(self) -> GetAsyncQueueStatusOutput: path_fmt="/development/async_queue_status", path_args=[], body=None, + query=None, success_code=200, error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), @@ -1008,6 +1070,7 @@ async def get_async_queue_status_production(self) -> GetAsyncQueueStatusOutput: path_fmt="/production/async_queue_status", path_args=[], body=None, + query=None, success_code=200, error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), @@ -1022,6 +1085,7 @@ async def get_async_queue_status_regional(self) -> GetAsyncQueueStatusOutput: path_fmt="/async_queue_status", path_args=[], body=None, + query=None, success_code=200, error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), @@ -1038,12 +1102,13 @@ async def get_async_request_status( path_fmt="/async_request/{}", path_args=[request_id], body=None, + query=None, success_code=200, error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), ) - async def predict(self, *, env_name: str, body: PredictInput) -> PredictOutput: + async def predict(self, *, env_name: str, request: PredictInput) -> PredictOutput: """Call the model deployment associated with a specified environment.""" return await self._do_json( PredictOutput, @@ -1051,7 +1116,8 @@ async def predict(self, *, env_name: str, body: PredictInput) -> PredictOutput: method="POST", path_fmt="/environments/{}/predict", path_args=[env_name], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -1065,7 +1131,7 @@ async def predict(self, *, env_name: str, body: PredictInput) -> PredictOutput: ) async def predict_deployment( - self, *, deployment_id: str, body: PredictInput + self, *, deployment_id: str, request: PredictInput ) -> PredictOutput: """Call a specific deployment of a model by deployment ID.""" return await self._do_json( @@ -1074,7 +1140,8 @@ async def predict_deployment( method="POST", path_fmt="/deployment/{}/predict", path_args=[deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -1087,7 +1154,7 @@ async def predict_deployment( ), ) - async def predict_development(self, *, body: PredictInput) -> PredictOutput: + async def predict_development(self, *, request: PredictInput) -> PredictOutput: """Call the development deployment of a model.""" return await self._do_json( PredictOutput, @@ -1095,7 +1162,8 @@ async def predict_development(self, *, body: PredictInput) -> PredictOutput: method="POST", path_fmt="/development/predict", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -1108,7 +1176,7 @@ async def predict_development(self, *, body: PredictInput) -> PredictOutput: ), ) - async def predict_production(self, *, body: PredictInput) -> PredictOutput: + async def predict_production(self, *, request: PredictInput) -> PredictOutput: """Call the production environment of a model.""" return await self._do_json( PredictOutput, @@ -1116,7 +1184,8 @@ async def predict_production(self, *, body: PredictInput) -> PredictOutput: method="POST", path_fmt="/production/predict", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -1129,7 +1198,7 @@ async def predict_production(self, *, body: PredictInput) -> PredictOutput: ), ) - async def predict_regional(self, *, body: PredictInput) -> PredictOutput: + async def predict_regional(self, *, request: PredictInput) -> PredictOutput: """Call a regional environment of a model.""" return await self._do_json( PredictOutput, @@ -1137,7 +1206,8 @@ async def predict_regional(self, *, body: PredictInput) -> PredictOutput: method="POST", path_fmt="/predict", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -1151,7 +1221,7 @@ async def predict_regional(self, *, body: PredictInput) -> PredictOutput: ) async def run_remote( - self, *, env_name: str, body: RunRemoteInput + self, *, env_name: str, request: RunRemoteInput ) -> RunRemoteOutput: """Call the chain deployment associated with a specified environment.""" return await self._do_json( @@ -1160,7 +1230,8 @@ async def run_remote( method="POST", path_fmt="/environments/{}/run_remote", path_args=[env_name], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -1174,7 +1245,7 @@ async def run_remote( ) async def run_remote_deployment( - self, *, deployment_id: str, body: RunRemoteInput + self, *, deployment_id: str, request: RunRemoteInput ) -> RunRemoteOutput: """Call a specific chain deployment by deployment ID.""" return await self._do_json( @@ -1183,7 +1254,8 @@ async def run_remote_deployment( method="POST", path_fmt="/deployment/{}/run_remote", path_args=[deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -1196,7 +1268,9 @@ async def run_remote_deployment( ), ) - async def run_remote_development(self, *, body: RunRemoteInput) -> RunRemoteOutput: + async def run_remote_development( + self, *, request: RunRemoteInput + ) -> RunRemoteOutput: """Call the development deployment of a chain.""" return await self._do_json( RunRemoteOutput, @@ -1204,7 +1278,8 @@ async def run_remote_development(self, *, body: RunRemoteInput) -> RunRemoteOutp method="POST", path_fmt="/development/run_remote", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -1217,7 +1292,9 @@ async def run_remote_development(self, *, body: RunRemoteInput) -> RunRemoteOutp ), ) - async def run_remote_production(self, *, body: RunRemoteInput) -> RunRemoteOutput: + async def run_remote_production( + self, *, request: RunRemoteInput + ) -> RunRemoteOutput: """Call the production environment of a chain.""" return await self._do_json( RunRemoteOutput, @@ -1225,7 +1302,8 @@ async def run_remote_production(self, *, body: RunRemoteInput) -> RunRemoteOutpu method="POST", path_fmt="/production/run_remote", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -1238,7 +1316,7 @@ async def run_remote_production(self, *, body: RunRemoteInput) -> RunRemoteOutpu ), ) - async def run_remote_regional(self, *, body: RunRemoteInput) -> RunRemoteOutput: + async def run_remote_regional(self, *, request: RunRemoteInput) -> RunRemoteOutput: """Call a regional environment of a chain.""" return await self._do_json( RunRemoteOutput, @@ -1246,7 +1324,8 @@ async def run_remote_regional(self, *, body: RunRemoteInput) -> RunRemoteOutput: method="POST", path_fmt="/run_remote", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes={ 400: "ErrorResponse", @@ -1267,6 +1346,7 @@ async def wake(self, *, env_name: str) -> None: path_fmt="/environments/{}/wake", path_args=[env_name], body=None, + query=None, success_code=202, error_codes={401: "ErrorResponse"}, ) @@ -1280,6 +1360,7 @@ async def wake_deployment(self, *, deployment_id: str) -> None: path_fmt="/deployment/{}/wake", path_args=[deployment_id], body=None, + query=None, success_code=202, error_codes={401: "ErrorResponse"}, ) @@ -1293,6 +1374,7 @@ async def wake_development(self) -> None: path_fmt="/development/wake", path_args=[], body=None, + query=None, success_code=202, error_codes={401: "ErrorResponse"}, ) @@ -1306,6 +1388,7 @@ async def wake_production(self) -> None: path_fmt="/production/wake", path_args=[], body=None, + query=None, success_code=202, error_codes={401: "ErrorResponse"}, ) @@ -1319,6 +1402,7 @@ async def wake_regional(self) -> None: path_fmt="/wake", path_args=[], body=None, + query=None, success_code=202, error_codes={401: "ErrorResponse"}, ) @@ -1331,10 +1415,25 @@ async def _do(self, request: _ApiRequest) -> httpx.Response: json_body = None if request.body is not None: if isinstance(request.body, BaseModel): - json_body = request.body.model_dump(mode="json") + # Only fields the caller set are sent, so unset fields fall + # back to the server default rather than being reset here. + # An explicit None is kept, since null can mean "clear". + json_body = request.body.model_dump(mode="json", exclude_unset=True) else: json_body = request.body - response = await self._http_client.request(request.method, path, json=json_body) + params = None + if request.query is not None: + if isinstance(request.query, BaseModel): + # As above, plus dropping None: a null query parameter is + # meaningless and would otherwise serialize as an empty string. + params = request.query.model_dump( + mode="json", exclude_unset=True, exclude_none=True + ) + else: + params = request.query + response = await self._http_client.request( + request.method, path, json=json_body, params=params + ) if response.status_code != request.success_code: if request.error_codes and response.status_code in request.error_codes: error_name = request.error_codes[response.status_code] diff --git a/baseten/client/managementapi/__init__.py b/baseten/client/managementapi/__init__.py index b11f82a..9dc09df 100644 --- a/baseten/client/managementapi/__init__.py +++ b/baseten/client/managementapi/__init__.py @@ -135,8 +135,10 @@ GcpOidcDockerAuth, GcpServiceAccountJsonDockerAuth, GetAuthCodesResponse, + GetBillingUsageSummaryRequest, GetBlobCredentialsResponse, GetCacheSummaryResponse, + GetChainsDeploymentsChainletsLogsRequest, GetDeploymentConfigRequest, GetDeploymentLogsRequest, GetDeploymentMetricsRequest, @@ -145,15 +147,28 @@ GetEnvironmentMetricsRequest, GetLogsResponse, GetLoopsCapabilitiesResponse, + GetLoopsCheckpointsRequest, GetLoopsDeploymentLogsRequest, GetLoopsDeploymentMetricsRequest, GetLoopsDeploymentMetricsResponse, GetLoopsDeploymentResponse, + GetLoopsDeploymentsLogsRequest, GetLoopsRunResponse, + GetLoopsRunsRequest, GetLoopsSamplerResponse, GetLoopsSessionResponse, GetLoopsUserConfigResponse, + GetModelApisRequest, GetModelMetricsResponse, + GetModelsDeploymentsConfigRequest, + GetModelsDeploymentsLogsRequest, + GetModelsDeploymentsMetricsRequest, + GetModelsDeploymentsRequest, + GetModelsEnvironmentsLogsRequest, + GetModelsEnvironmentsMetricsRequest, + GetModelsRequest, + GetTeamsModelsRequest, + GetTeamsRequest, GetTrainingGpuCapacityResponse, GetTrainingJobCheckpointFilesRequest, GetTrainingJobCheckpointFilesResponse, @@ -164,6 +179,10 @@ GetTrainingJobQueueContextResponse, GetTrainingJobResponse, GetTrainingProjectResponse, + GetTrainingProjectsJobsCheckpointFilesRequest, + GetTrainingProjectsJobsLogsRequest, + GetTrainingProjectsJobsMetricsRequest, + GetUsersRequest, GitInfo, Group, GroupHierarchy, @@ -481,8 +500,10 @@ "GcpOidcDockerAuth", "GcpServiceAccountJsonDockerAuth", "GetAuthCodesResponse", + "GetBillingUsageSummaryRequest", "GetBlobCredentialsResponse", "GetCacheSummaryResponse", + "GetChainsDeploymentsChainletsLogsRequest", "GetDeploymentConfigRequest", "GetDeploymentLogsRequest", "GetDeploymentMetricsRequest", @@ -491,15 +512,28 @@ "GetEnvironmentMetricsRequest", "GetLogsResponse", "GetLoopsCapabilitiesResponse", + "GetLoopsCheckpointsRequest", "GetLoopsDeploymentLogsRequest", "GetLoopsDeploymentMetricsRequest", "GetLoopsDeploymentMetricsResponse", "GetLoopsDeploymentResponse", + "GetLoopsDeploymentsLogsRequest", "GetLoopsRunResponse", + "GetLoopsRunsRequest", "GetLoopsSamplerResponse", "GetLoopsSessionResponse", "GetLoopsUserConfigResponse", + "GetModelApisRequest", "GetModelMetricsResponse", + "GetModelsDeploymentsConfigRequest", + "GetModelsDeploymentsLogsRequest", + "GetModelsDeploymentsMetricsRequest", + "GetModelsDeploymentsRequest", + "GetModelsEnvironmentsLogsRequest", + "GetModelsEnvironmentsMetricsRequest", + "GetModelsRequest", + "GetTeamsModelsRequest", + "GetTeamsRequest", "GetTrainingGpuCapacityResponse", "GetTrainingJobCheckpointFilesRequest", "GetTrainingJobCheckpointFilesResponse", @@ -510,6 +544,10 @@ "GetTrainingJobQueueContextResponse", "GetTrainingJobResponse", "GetTrainingProjectResponse", + "GetTrainingProjectsJobsCheckpointFilesRequest", + "GetTrainingProjectsJobsLogsRequest", + "GetTrainingProjectsJobsMetricsRequest", + "GetUsersRequest", "GitInfo", "Group", "GroupHierarchy", diff --git a/baseten/client/managementapi/_client.py b/baseten/client/managementapi/_client.py index 45a2d6e..9ad43da 100644 --- a/baseten/client/managementapi/_client.py +++ b/baseten/client/managementapi/_client.py @@ -63,20 +63,35 @@ Environments, GatewayKeyInfo, GetAuthCodesResponse, + GetBillingUsageSummaryRequest, GetBlobCredentialsResponse, GetCacheSummaryResponse, + GetChainsDeploymentsChainletsLogsRequest, GetDeploymentLogsRequest, GetDeploymentPatchesStateResponse, GetLogsResponse, GetLoopsCapabilitiesResponse, + GetLoopsCheckpointsRequest, GetLoopsDeploymentMetricsRequest, GetLoopsDeploymentMetricsResponse, GetLoopsDeploymentResponse, + GetLoopsDeploymentsLogsRequest, GetLoopsRunResponse, + GetLoopsRunsRequest, GetLoopsSamplerResponse, GetLoopsSessionResponse, GetLoopsUserConfigResponse, + GetModelApisRequest, GetModelMetricsResponse, + GetModelsDeploymentsConfigRequest, + GetModelsDeploymentsLogsRequest, + GetModelsDeploymentsMetricsRequest, + GetModelsDeploymentsRequest, + GetModelsEnvironmentsLogsRequest, + GetModelsEnvironmentsMetricsRequest, + GetModelsRequest, + GetTeamsModelsRequest, + GetTeamsRequest, GetTrainingGpuCapacityResponse, GetTrainingJobCheckpointFilesResponse, GetTrainingJobCheckpointsResponse, @@ -86,6 +101,10 @@ GetTrainingJobQueueContextResponse, GetTrainingJobResponse, GetTrainingProjectResponse, + GetTrainingProjectsJobsCheckpointFilesRequest, + GetTrainingProjectsJobsLogsRequest, + GetTrainingProjectsJobsMetricsRequest, + GetUsersRequest, Group, GroupsResponse, InstanceTypePrices, @@ -186,6 +205,7 @@ class _ApiRequest: path_fmt: str path_args: list[str] body: Any + query: Any success_code: int error_codes: dict[int, str] | None @@ -211,6 +231,7 @@ def delete_api_keys(self, *, api_key_prefix: str) -> APIKeyTombstone: path_fmt="/v1/api_keys/{}", path_args=[api_key_prefix], body=None, + query=None, success_code=200, error_codes=None, ), @@ -225,6 +246,7 @@ def delete_chains(self, *, chain_id: str) -> ChainTombstone: path_fmt="/v1/chains/{}", path_args=[chain_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -241,6 +263,7 @@ def delete_chains_deployments( path_fmt="/v1/chains/{}/deployments/{}", path_args=[chain_id, chain_deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -255,6 +278,7 @@ def delete_gateway_endpoints(self, *, endpoint_id: str) -> EndpointTombstone: path_fmt="/v1/gateway/endpoints/{}", path_args=[endpoint_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -271,6 +295,7 @@ def delete_library_listings( path_fmt="/v1/library_listings/{}", path_args=[user_defined_listing_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -287,6 +312,7 @@ def delete_library_listings_versions( path_fmt="/v1/library_listings/{}/versions/{}", path_args=[user_defined_listing_id, version_tag], body=None, + query=None, success_code=200, error_codes=None, ), @@ -301,6 +327,7 @@ def delete_models(self, *, model_id: str) -> ModelTombstone: path_fmt="/v1/models/{}", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -317,6 +344,7 @@ def delete_models_deployments( path_fmt="/v1/models/{}/deployments/{}", path_args=[model_id, deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -333,6 +361,7 @@ def delete_models_deployments_replicas( path_fmt="/v1/models/{}/deployments/{}/replicas/{}", path_args=[model_id, deployment_id, replica_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -347,6 +376,7 @@ def delete_secrets(self, *, secret_name: str) -> SecretTombstone: path_fmt="/v1/secrets/{}", path_args=[secret_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -363,6 +393,7 @@ def delete_teams_secrets( path_fmt="/v1/teams/{}/secrets/{}", path_args=[team_id, secret_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -379,6 +410,7 @@ def delete_training_projects( path_fmt="/v1/training_projects/{}", path_args=[training_project_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -395,6 +427,7 @@ def delete_training_projects_jobs( path_fmt="/v1/training_projects/{}/jobs/{}", path_args=[training_project_id, training_job_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -409,12 +442,15 @@ def get_api_keys(self) -> APIKeys: path_fmt="/v1/api_keys", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), ) - def get_billing_usage_summary(self) -> UsageSummary: + def get_billing_usage_summary( + self, *, request: GetBillingUsageSummaryRequest + ) -> UsageSummary: """Gets billing usage summary for a date range""" return self._do_json( UsageSummary, @@ -423,6 +459,7 @@ def get_billing_usage_summary(self) -> UsageSummary: path_fmt="/v1/billing/usage_summary", path_args=[], body=None, + query=request, success_code=200, error_codes=None, ), @@ -437,6 +474,7 @@ def get_blobs_credentials_model(self) -> GetBlobCredentialsResponse: path_fmt="/v1/blobs/credentials/model", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -451,6 +489,7 @@ def get_blobs_credentials_train(self) -> GetBlobCredentialsResponse: path_fmt="/v1/blobs/credentials/train", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -465,6 +504,7 @@ def get_chains(self) -> Chains: path_fmt="/v1/chains", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -479,6 +519,7 @@ def get_chains_chain_id(self, *, chain_id: str) -> Chain: path_fmt="/v1/chains/{}", path_args=[chain_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -493,6 +534,7 @@ def get_chains_deployments(self, *, chain_id: str) -> ChainDeployments: path_fmt="/v1/chains/{}/deployments", path_args=[chain_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -509,13 +551,19 @@ def get_chains_deployments_chain_deployment_id( path_fmt="/v1/chains/{}/deployments/{}", path_args=[chain_id, chain_deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), ) def get_chains_deployments_chainlets_logs( - self, *, chain_id: str, chain_deployment_id: str, chainlet_id: str + self, + *, + chain_id: str, + chain_deployment_id: str, + chainlet_id: str, + request: GetChainsDeploymentsChainletsLogsRequest | None = None, ) -> GetLogsResponse: """Gets the logs for a chainlet within a chain deployment""" return self._do_json( @@ -525,6 +573,7 @@ def get_chains_deployments_chainlets_logs( path_fmt="/v1/chains/{}/deployments/{}/chainlets/{}/logs", path_args=[chain_id, chain_deployment_id, chainlet_id], body=None, + query=request, success_code=200, error_codes=None, ), @@ -539,6 +588,7 @@ def get_chains_environments(self, *, chain_id: str) -> Environments: path_fmt="/v1/chains/{}/environments", path_args=[chain_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -555,6 +605,7 @@ def get_chains_environments_env_name( path_fmt="/v1/chains/{}/environments/{}", path_args=[chain_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -569,6 +620,7 @@ def get_environment_groups(self) -> EnvironmentGroups: path_fmt="/v1/environment_groups", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -583,6 +635,7 @@ def get_environment_groups_env_name(self, *, env_name: str) -> EnvironmentGroup: path_fmt="/v1/environment_groups/{}", path_args=[env_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -597,6 +650,7 @@ def get_gateway_endpoints(self) -> EndpointsResponse: path_fmt="/v1/gateway/endpoints", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -611,6 +665,7 @@ def get_gateway_endpoints_endpoint_id(self, *, endpoint_id: str) -> Endpoint: path_fmt="/v1/gateway/endpoints/{}", path_args=[endpoint_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -625,6 +680,7 @@ def get_gateway_groups(self) -> GroupsResponse: path_fmt="/v1/gateway/groups", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -639,6 +695,7 @@ def get_gateway_groups_api_keys(self, *, group_id: str) -> KeysForGroupResponse: path_fmt="/v1/gateway/groups/{}/api_keys", path_args=[group_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -655,6 +712,7 @@ def get_gateway_groups_api_keys_api_key_prefix( path_fmt="/v1/gateway/groups/{}/api_keys/{}", path_args=[group_id, api_key_prefix], body=None, + query=None, success_code=200, error_codes=None, ), @@ -669,6 +727,7 @@ def get_gateway_groups_group_id(self, *, group_id: str) -> Group: path_fmt="/v1/gateway/groups/{}", path_args=[group_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -683,6 +742,7 @@ def get_instance_type_prices(self) -> InstanceTypePrices: path_fmt="/v1/instance_type_prices", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -697,6 +757,7 @@ def get_instance_types(self) -> InstanceTypes: path_fmt="/v1/instance_types", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -711,6 +772,7 @@ def get_library_listings(self) -> LibraryListings: path_fmt="/v1/library_listings", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -727,6 +789,7 @@ def get_library_listings_user_defined_listing_id( path_fmt="/v1/library_listings/{}", path_args=[user_defined_listing_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -743,6 +806,7 @@ def get_library_listings_versions( path_fmt="/v1/library_listings/{}/versions", path_args=[user_defined_listing_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -759,6 +823,7 @@ def get_library_listings_versions_version_tag( path_fmt="/v1/library_listings/{}/versions/{}", path_args=[user_defined_listing_id, version_tag], body=None, + query=None, success_code=200, error_codes=None, ), @@ -773,12 +838,15 @@ def get_loops_capabilities(self) -> GetLoopsCapabilitiesResponse: path_fmt="/v1/loops/capabilities", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), ) - def get_loops_checkpoints(self) -> ListLoopsCheckpointsResponse: + def get_loops_checkpoints( + self, *, request: GetLoopsCheckpointsRequest | None = None + ) -> ListLoopsCheckpointsResponse: """Lists Loops checkpoints""" return self._do_json( ListLoopsCheckpointsResponse, @@ -787,6 +855,7 @@ def get_loops_checkpoints(self) -> ListLoopsCheckpointsResponse: path_fmt="/v1/loops/checkpoints", path_args=[], body=None, + query=request, success_code=200, error_codes=None, ), @@ -803,6 +872,7 @@ def get_loops_checkpoints_files( path_fmt="/v1/loops/checkpoints/{}/files", path_args=[checkpoint_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -817,6 +887,7 @@ def get_loops_deployments(self) -> ListLoopsDeploymentsResponse: path_fmt="/v1/loops/deployments", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -833,12 +904,18 @@ def get_loops_deployments_deployment_id( path_fmt="/v1/loops/deployments/{}", path_args=[deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), ) - def get_loops_deployments_logs(self, *, deployment_id: str) -> GetLogsResponse: + def get_loops_deployments_logs( + self, + *, + deployment_id: str, + request: GetLoopsDeploymentsLogsRequest | None = None, + ) -> GetLogsResponse: """Gets logs for a Loops trainer deployment""" return self._do_json( GetLogsResponse, @@ -847,12 +924,15 @@ def get_loops_deployments_logs(self, *, deployment_id: str) -> GetLogsResponse: path_fmt="/v1/loops/deployments/{}/logs", path_args=[deployment_id], body=None, + query=request, success_code=200, error_codes=None, ), ) - def get_loops_runs(self) -> ListLoopsRunsResponse: + def get_loops_runs( + self, *, request: GetLoopsRunsRequest | None = None + ) -> ListLoopsRunsResponse: """Lists Loops runs""" return self._do_json( ListLoopsRunsResponse, @@ -861,6 +941,7 @@ def get_loops_runs(self) -> ListLoopsRunsResponse: path_fmt="/v1/loops/runs", path_args=[], body=None, + query=request, success_code=200, error_codes=None, ), @@ -875,6 +956,7 @@ def get_loops_runs_run_id(self, *, run_id: str) -> GetLoopsRunResponse: path_fmt="/v1/loops/runs/{}", path_args=[run_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -889,6 +971,7 @@ def get_loops_samplers(self) -> ListLoopsSamplersResponse: path_fmt="/v1/loops/samplers", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -905,6 +988,7 @@ def get_loops_samplers_sampler_id( path_fmt="/v1/loops/samplers/{}", path_args=[sampler_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -919,6 +1003,7 @@ def get_loops_sessions(self, *, session_id: str) -> GetLoopsSessionResponse: path_fmt="/v1/loops/sessions/{}", path_args=[session_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -933,12 +1018,15 @@ def get_loops_user_config(self) -> GetLoopsUserConfigResponse: path_fmt="/v1/loops/user_config", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), ) - def get_model_apis(self) -> ModelAPIsResponse: + def get_model_apis( + self, *, request: GetModelApisRequest | None = None + ) -> ModelAPIsResponse: """Lists Model APIs""" return self._do_json( ModelAPIsResponse, @@ -947,6 +1035,7 @@ def get_model_apis(self) -> ModelAPIsResponse: path_fmt="/v1/model_apis", path_args=[], body=None, + query=request, success_code=200, error_codes=None, ), @@ -961,6 +1050,7 @@ def get_model_apis_model_api_name(self, *, model_api_name: str) -> ModelAPI: path_fmt="/v1/model_apis/{}", path_args=[model_api_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -975,6 +1065,7 @@ def get_model_apis_snapshots(self) -> ModelWeightSnapshot: path_fmt="/v1/model_apis/snapshots", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -991,12 +1082,13 @@ def get_model_apis_snapshots_model_id( path_fmt="/v1/model_apis/snapshots/{}", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), ) - def get_models(self) -> Models: + def get_models(self, *, request: GetModelsRequest | None = None) -> Models: """Gets all models""" return self._do_json( Models, @@ -1005,12 +1097,15 @@ def get_models(self) -> Models: path_fmt="/v1/models", path_args=[], body=None, + query=request, success_code=200, error_codes=None, ), ) - def get_models_deployments(self, *, model_id: str) -> Deployments: + def get_models_deployments( + self, *, model_id: str, request: GetModelsDeploymentsRequest | None = None + ) -> Deployments: """Gets all deployments of a model""" return self._do_json( Deployments, @@ -1019,13 +1114,18 @@ def get_models_deployments(self, *, model_id: str) -> Deployments: path_fmt="/v1/models/{}/deployments", path_args=[model_id], body=None, + query=request, success_code=200, error_codes=None, ), ) def get_models_deployments_config( - self, *, model_id: str, deployment_id: str + self, + *, + model_id: str, + deployment_id: str, + request: GetModelsDeploymentsConfigRequest | None = None, ) -> DeploymentConfigResponse: """Gets a deployment's config""" return self._do_json( @@ -1035,6 +1135,7 @@ def get_models_deployments_config( path_fmt="/v1/models/{}/deployments/{}/config", path_args=[model_id, deployment_id], body=None, + query=request, success_code=200, error_codes=None, ), @@ -1051,6 +1152,7 @@ def get_models_deployments_deployment_id( path_fmt="/v1/models/{}/deployments/{}", path_args=[model_id, deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1065,6 +1167,7 @@ def get_models_deployments_development(self, *, model_id: str) -> Deployment: path_fmt="/v1/models/{}/deployments/development", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1081,13 +1184,18 @@ def get_models_deployments_download( path_fmt="/v1/models/{}/deployments/{}/download", path_args=[model_id, deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), ) def get_models_deployments_logs( - self, *, model_id: str, deployment_id: str + self, + *, + model_id: str, + deployment_id: str, + request: GetModelsDeploymentsLogsRequest | None = None, ) -> GetLogsResponse: """Gets the logs for a model deployment""" return self._do_json( @@ -1097,13 +1205,18 @@ def get_models_deployments_logs( path_fmt="/v1/models/{}/deployments/{}/logs", path_args=[model_id, deployment_id], body=None, + query=request, success_code=200, error_codes=None, ), ) def get_models_deployments_metrics( - self, *, model_id: str, deployment_id: str + self, + *, + model_id: str, + deployment_id: str, + request: GetModelsDeploymentsMetricsRequest | None = None, ) -> GetModelMetricsResponse: """Gets the metrics for a model deployment""" return self._do_json( @@ -1113,6 +1226,7 @@ def get_models_deployments_metrics( path_fmt="/v1/models/{}/deployments/{}/metrics", path_args=[model_id, deployment_id], body=None, + query=request, success_code=200, error_codes=None, ), @@ -1129,6 +1243,7 @@ def get_models_deployments_patches_state( path_fmt="/v1/models/{}/deployments/{}/patches/state", path_args=[model_id, deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1143,6 +1258,7 @@ def get_models_deployments_production(self, *, model_id: str) -> Deployment: path_fmt="/v1/models/{}/deployments/production", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1157,6 +1273,7 @@ def get_models_environments(self, *, model_id: str) -> Environments: path_fmt="/v1/models/{}/environments", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1173,13 +1290,18 @@ def get_models_environments_env_name( path_fmt="/v1/models/{}/environments/{}", path_args=[model_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), ) def get_models_environments_logs( - self, *, model_id: str, env_name: str + self, + *, + model_id: str, + env_name: str, + request: GetModelsEnvironmentsLogsRequest | None = None, ) -> GetLogsResponse: """Gets the logs for a model environment""" return self._do_json( @@ -1189,13 +1311,18 @@ def get_models_environments_logs( path_fmt="/v1/models/{}/environments/{}/logs", path_args=[model_id, env_name], body=None, + query=request, success_code=200, error_codes=None, ), ) def get_models_environments_metrics( - self, *, model_id: str, env_name: str + self, + *, + model_id: str, + env_name: str, + request: GetModelsEnvironmentsMetricsRequest | None = None, ) -> GetModelMetricsResponse: """Gets the metrics for a model environment.""" return self._do_json( @@ -1205,6 +1332,7 @@ def get_models_environments_metrics( path_fmt="/v1/models/{}/environments/{}/metrics", path_args=[model_id, env_name], body=None, + query=request, success_code=200, error_codes=None, ), @@ -1219,6 +1347,7 @@ def get_models_model_id(self, *, model_id: str) -> Model: path_fmt="/v1/models/{}", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1233,12 +1362,13 @@ def get_secrets(self) -> Secrets: path_fmt="/v1/secrets", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), ) - def get_teams(self) -> Teams: + def get_teams(self, *, request: GetTeamsRequest | None = None) -> Teams: """Lists all teams""" return self._do_json( Teams, @@ -1247,6 +1377,7 @@ def get_teams(self) -> Teams: path_fmt="/v1/teams", path_args=[], body=None, + query=request, success_code=200, error_codes=None, ), @@ -1261,6 +1392,7 @@ def get_teams_environment_groups(self, *, team_id: str) -> EnvironmentGroups: path_fmt="/v1/teams/{}/environment_groups", path_args=[team_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1277,12 +1409,15 @@ def get_teams_environment_groups_env_name( path_fmt="/v1/teams/{}/environment_groups/{}", path_args=[team_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), ) - def get_teams_models(self, *, team_id: str) -> Models: + def get_teams_models( + self, *, team_id: str, request: GetTeamsModelsRequest | None = None + ) -> Models: """Gets all models""" return self._do_json( Models, @@ -1291,6 +1426,7 @@ def get_teams_models(self, *, team_id: str) -> Models: path_fmt="/v1/teams/{}/models", path_args=[team_id], body=None, + query=request, success_code=200, error_codes=None, ), @@ -1305,6 +1441,7 @@ def get_teams_secrets(self, *, team_id: str) -> Secrets: path_fmt="/v1/teams/{}/secrets", path_args=[team_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1319,6 +1456,7 @@ def get_teams_team_id(self, *, team_id: str) -> Team: path_fmt="/v1/teams/{}", path_args=[team_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1333,6 +1471,7 @@ def get_training_capacity(self) -> GetTrainingGpuCapacityResponse: path_fmt="/v1/training/capacity", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1349,6 +1488,7 @@ def get_training_jobs_queue_context( path_fmt="/v1/training/jobs/{}/queue_context", path_args=[training_job_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1363,6 +1503,7 @@ def get_training_projects(self) -> ListTrainingProjectsResponse: path_fmt="/v1/training_projects", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1379,6 +1520,7 @@ def get_training_projects_cache_summary( path_fmt="/v1/training_projects/{}/cache/summary", path_args=[training_project_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1395,6 +1537,7 @@ def get_training_projects_jobs( path_fmt="/v1/training_projects/{}/jobs", path_args=[training_project_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1411,13 +1554,18 @@ def get_training_projects_jobs_auth_codes( path_fmt="/v1/training_projects/{}/jobs/{}/auth_codes", path_args=[training_project_id, training_job_id], body=None, + query=None, success_code=200, error_codes=None, ), ) def get_training_projects_jobs_checkpoint_files( - self, *, training_project_id: str, training_job_id: str + self, + *, + training_project_id: str, + training_job_id: str, + request: GetTrainingProjectsJobsCheckpointFilesRequest | None = None, ) -> GetTrainingJobCheckpointFilesResponse: """Gets training job checkpoint files""" return self._do_json( @@ -1427,6 +1575,7 @@ def get_training_projects_jobs_checkpoint_files( path_fmt="/v1/training_projects/{}/jobs/{}/checkpoint_files", path_args=[training_project_id, training_job_id], body=None, + query=request, success_code=200, error_codes=None, ), @@ -1443,6 +1592,7 @@ def get_training_projects_jobs_checkpoints( path_fmt="/v1/training_projects/{}/jobs/{}/checkpoints", path_args=[training_project_id, training_job_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1459,13 +1609,18 @@ def get_training_projects_jobs_download( path_fmt="/v1/training_projects/{}/jobs/{}/download", path_args=[training_project_id, training_job_id], body=None, + query=None, success_code=200, error_codes=None, ), ) def get_training_projects_jobs_logs( - self, *, training_project_id: str, training_job_id: str + self, + *, + training_project_id: str, + training_job_id: str, + request: GetTrainingProjectsJobsLogsRequest | None = None, ) -> GetLogsResponse: """Gets the logs for a training job""" return self._do_json( @@ -1475,13 +1630,18 @@ def get_training_projects_jobs_logs( path_fmt="/v1/training_projects/{}/jobs/{}/logs", path_args=[training_project_id, training_job_id], body=None, + query=request, success_code=200, error_codes=None, ), ) def get_training_projects_jobs_metrics( - self, *, training_project_id: str, training_job_id: str + self, + *, + training_project_id: str, + training_job_id: str, + request: GetTrainingProjectsJobsMetricsRequest | None = None, ) -> GetTrainingJobMetricsResponse: """Gets the metrics for a training job""" return self._do_json( @@ -1491,6 +1651,7 @@ def get_training_projects_jobs_metrics( path_fmt="/v1/training_projects/{}/jobs/{}/metrics", path_args=[training_project_id, training_job_id], body=None, + query=request, success_code=200, error_codes=None, ), @@ -1507,6 +1668,7 @@ def get_training_projects_jobs_training_job_id( path_fmt="/v1/training_projects/{}/jobs/{}", path_args=[training_project_id, training_job_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1523,12 +1685,13 @@ def get_training_projects_training_project_id( path_fmt="/v1/training_projects/{}", path_args=[training_project_id], body=None, + query=None, success_code=200, error_codes=None, ), ) - def get_users(self) -> UsersResponse: + def get_users(self, *, request: GetUsersRequest | None = None) -> UsersResponse: """Lists users in the workspace""" return self._do_json( UsersResponse, @@ -1537,6 +1700,7 @@ def get_users(self) -> UsersResponse: path_fmt="/v1/users", path_args=[], body=None, + query=request, success_code=200, error_codes=None, ), @@ -1551,6 +1715,7 @@ def get_users_me(self) -> UserInfo: path_fmt="/v1/users/me", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -1565,13 +1730,14 @@ def get_users_user_id(self, *, user_id: str) -> UserInfo: path_fmt="/v1/users/{}", path_args=[user_id], body=None, + query=None, success_code=200, error_codes=None, ), ) def patch_chains_environments( - self, *, chain_id: str, env_name: str, body: UpdateChainEnvironmentRequest + self, *, chain_id: str, env_name: str, request: UpdateChainEnvironmentRequest ) -> UpdateChainEnvironmentResponse: """Updates a chain environment's settings""" return self._do_json( @@ -1580,7 +1746,8 @@ def patch_chains_environments( method="PATCH", path_fmt="/v1/chains/{}/environments/{}", path_args=[chain_id, env_name], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -1591,7 +1758,7 @@ def patch_chains_environments_chainlet_settings_autoscaling_settings( *, chain_id: str, env_name: str, - body: UpdateChainletEnvironmentAutoscalingSettingsRequest, + request: UpdateChainletEnvironmentAutoscalingSettingsRequest, ) -> UpdateAutoscalingSettingsResponse: """Updates a chainlet environment's autoscaling settings""" return self._do_json( @@ -1600,14 +1767,15 @@ def patch_chains_environments_chainlet_settings_autoscaling_settings( method="PATCH", path_fmt="/v1/chains/{}/environments/{}/chainlet_settings/autoscaling_settings", path_args=[chain_id, env_name], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def patch_environment_groups( - self, *, env_name: str, body: UpdateEnvironmentGroupRequest + self, *, env_name: str, request: UpdateEnvironmentGroupRequest ) -> EnvironmentGroup: """Updates an environment group's restriction settings""" return self._do_json( @@ -1616,14 +1784,15 @@ def patch_environment_groups( method="PATCH", path_fmt="/v1/environment_groups/{}", path_args=[env_name], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def patch_gateway_endpoints( - self, *, endpoint_id: str, body: UpdateEndpointRequest + self, *, endpoint_id: str, request: UpdateEndpointRequest ) -> Endpoint: """Updates a Gateway endpoint""" return self._do_json( @@ -1632,13 +1801,16 @@ def patch_gateway_endpoints( method="PATCH", path_fmt="/v1/gateway/endpoints/{}", path_args=[endpoint_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) - def patch_gateway_groups(self, *, group_id: str, body: UpdateGroupRequest) -> Group: + def patch_gateway_groups( + self, *, group_id: str, request: UpdateGroupRequest + ) -> Group: """Updates a group""" return self._do_json( Group, @@ -1646,14 +1818,15 @@ def patch_gateway_groups(self, *, group_id: str, body: UpdateGroupRequest) -> Gr method="PATCH", path_fmt="/v1/gateway/groups/{}", path_args=[group_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def patch_library_listings( - self, *, user_defined_listing_id: str, body: UpdateLibraryListingRequest + self, *, user_defined_listing_id: str, request: UpdateLibraryListingRequest ) -> LibraryListing: """Updates a library listing""" return self._do_json( @@ -1662,7 +1835,8 @@ def patch_library_listings( method="PATCH", path_fmt="/v1/library_listings/{}", path_args=[user_defined_listing_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -1673,7 +1847,7 @@ def patch_library_listings_versions( *, user_defined_listing_id: str, version_tag: str, - body: UpdateLibraryListingVersionRequest, + request: UpdateLibraryListingVersionRequest, ) -> LibraryListingVersion: """Updates a library listing version""" return self._do_json( @@ -1682,14 +1856,15 @@ def patch_library_listings_versions( method="PATCH", path_fmt="/v1/library_listings/{}/versions/{}", path_args=[user_defined_listing_id, version_tag], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def patch_loops_user_config( - self, *, body: PatchLoopsUserConfigRequest + self, *, request: PatchLoopsUserConfigRequest ) -> PatchLoopsUserConfigResponse: """Patches the caller's Loops user config""" return self._do_json( @@ -1698,14 +1873,15 @@ def patch_loops_user_config( method="PATCH", path_fmt="/v1/loops/user_config", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def patch_models_deployments_autoscaling_settings( - self, *, model_id: str, deployment_id: str, body: UpdateAutoscalingSettings + self, *, model_id: str, deployment_id: str, request: UpdateAutoscalingSettings ) -> UpdateAutoscalingSettingsResponse: """Updates a deployment's autoscaling settings""" return self._do_json( @@ -1714,14 +1890,15 @@ def patch_models_deployments_autoscaling_settings( method="PATCH", path_fmt="/v1/models/{}/deployments/{}/autoscaling_settings", path_args=[model_id, deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def patch_models_deployments_development_autoscaling_settings( - self, *, model_id: str, body: UpdateAutoscalingSettings + self, *, model_id: str, request: UpdateAutoscalingSettings ) -> UpdateAutoscalingSettingsResponse: """Updates a development deployment's autoscaling settings""" return self._do_json( @@ -1730,14 +1907,15 @@ def patch_models_deployments_development_autoscaling_settings( method="PATCH", path_fmt="/v1/models/{}/deployments/development/autoscaling_settings", path_args=[model_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def patch_models_deployments_production_autoscaling_settings( - self, *, model_id: str, body: UpdateAutoscalingSettings + self, *, model_id: str, request: UpdateAutoscalingSettings ) -> UpdateAutoscalingSettingsResponse: """Updates a production deployment's autoscaling settings""" return self._do_json( @@ -1746,14 +1924,15 @@ def patch_models_deployments_production_autoscaling_settings( method="PATCH", path_fmt="/v1/models/{}/deployments/production/autoscaling_settings", path_args=[model_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def patch_models_environments( - self, *, model_id: str, env_name: str, body: UpdateEnvironmentRequest + self, *, model_id: str, env_name: str, request: UpdateEnvironmentRequest ) -> UpdateAutoscalingSettingsResponse: """Updates an environment's settings""" return self._do_json( @@ -1762,14 +1941,15 @@ def patch_models_environments( method="PATCH", path_fmt="/v1/models/{}/environments/{}", path_args=[model_id, env_name], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def patch_teams_environment_groups( - self, *, team_id: str, env_name: str, body: UpdateEnvironmentGroupRequest + self, *, team_id: str, env_name: str, request: UpdateEnvironmentGroupRequest ) -> EnvironmentGroup: """Updates an environment group's restriction settings""" return self._do_json( @@ -1778,14 +1958,15 @@ def patch_teams_environment_groups( method="PATCH", path_fmt="/v1/teams/{}/environment_groups/{}", path_args=[team_id, env_name], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def patch_training_capacity( - self, *, body: PatchTeamTrainingGpuCapacityRequest + self, *, request: PatchTeamTrainingGpuCapacityRequest ) -> PatchTeamTrainingGpuCapacityResponse: """Sets a team's training GPU capacity""" return self._do_json( @@ -1794,7 +1975,8 @@ def patch_training_capacity( method="PATCH", path_fmt="/v1/training/capacity", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -1805,7 +1987,7 @@ def patch_training_projects_jobs( *, training_project_id: str, training_job_id: str, - body: UpdateTrainingJobRequest, + request: UpdateTrainingJobRequest, ) -> UpdateTrainingJobResponse: """Updates a training job""" return self._do_json( @@ -1814,7 +1996,8 @@ def patch_training_projects_jobs( method="PATCH", path_fmt="/v1/training_projects/{}/jobs/{}", path_args=[training_project_id, training_job_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -1826,7 +2009,7 @@ def patch_training_projects_jobs_interactive_sessions( training_project_id: str, training_job_id: str, session_id: str, - body: PatchInteractiveSessionRequest, + request: PatchInteractiveSessionRequest, ) -> PatchInteractiveSessionResponse: """Patches an interactive session""" return self._do_json( @@ -1835,13 +2018,14 @@ def patch_training_projects_jobs_interactive_sessions( method="PATCH", path_fmt="/v1/training_projects/{}/jobs/{}/interactive_sessions/{}", path_args=[training_project_id, training_job_id, session_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) - def post_api_keys(self, *, body: CreateAPIKeyRequest) -> APIKey: + def post_api_keys(self, *, request: CreateAPIKeyRequest) -> APIKey: """Creates an API key""" return self._do_json( APIKey, @@ -1849,7 +2033,8 @@ def post_api_keys(self, *, body: CreateAPIKeyRequest) -> APIKey: method="POST", path_fmt="/v1/api_keys", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -1866,13 +2051,14 @@ def post_chains_deployments_deactivate( path_fmt="/v1/chains/{}/deployments/{}/deactivate", path_args=[chain_id, chain_deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), ) def post_chains_environments( - self, *, chain_id: str, body: CreateChainEnvironmentRequest + self, *, chain_id: str, request: CreateChainEnvironmentRequest ) -> ChainEnvironment: """Creates a chain environment""" return self._do_json( @@ -1881,7 +2067,8 @@ def post_chains_environments( method="POST", path_fmt="/v1/chains/{}/environments", path_args=[chain_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -1892,7 +2079,7 @@ def post_chains_environments_chainlet_settings_instance_types_update( *, chain_id: str, env_name: str, - body: UpdateChainletEnvironmentInstanceTypeRequest, + request: UpdateChainletEnvironmentInstanceTypeRequest, ) -> UpdateChainletEnvironmentInstanceTypeResponse: """Updates a chainlet environment's instance type settings""" return self._do_json( @@ -1901,14 +2088,15 @@ def post_chains_environments_chainlet_settings_instance_types_update( method="POST", path_fmt="/v1/chains/{}/environments/{}/chainlet_settings/instance_types/update", path_args=[chain_id, env_name], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_chains_environments_promote( - self, *, chain_id: str, env_name: str, body: PromoteToChainEnvironmentRequest + self, *, chain_id: str, env_name: str, request: PromoteToChainEnvironmentRequest ) -> ChainDeployment: """Promotes a chain deployment to an environment""" return self._do_json( @@ -1917,13 +2105,14 @@ def post_chains_environments_promote( method="POST", path_fmt="/v1/chains/{}/environments/{}/promote", path_args=[chain_id, env_name], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) - def post_gateway_endpoints(self, *, body: CreateEndpointRequest) -> Endpoint: + def post_gateway_endpoints(self, *, request: CreateEndpointRequest) -> Endpoint: """Creates a Gateway endpoint""" return self._do_json( Endpoint, @@ -1931,13 +2120,14 @@ def post_gateway_endpoints(self, *, body: CreateEndpointRequest) -> Endpoint: method="POST", path_fmt="/v1/gateway/endpoints", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) - def post_gateway_groups(self, *, body: CreateGroupRequest) -> Group: + def post_gateway_groups(self, *, request: CreateGroupRequest) -> Group: """Creates a group""" return self._do_json( Group, @@ -1945,14 +2135,15 @@ def post_gateway_groups(self, *, body: CreateGroupRequest) -> Group: method="POST", path_fmt="/v1/gateway/groups", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_gateway_groups_api_keys( - self, *, group_id: str, body: CreateApiKeyForGroupRequest + self, *, group_id: str, request: CreateApiKeyForGroupRequest ) -> CreateApiKeyForGroupResponse: """Creates an API key for a group""" return self._do_json( @@ -1961,14 +2152,15 @@ def post_gateway_groups_api_keys( method="POST", path_fmt="/v1/gateway/groups/{}/api_keys", path_args=[group_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_gateway_groups_api_keys_register( - self, *, group_id: str, body: RegisterAPIKeyRequest + self, *, group_id: str, request: RegisterAPIKeyRequest ) -> RegisterAPIKeyResponse: """Registers an API key for a group""" return self._do_json( @@ -1977,14 +2169,15 @@ def post_gateway_groups_api_keys_register( method="POST", path_fmt="/v1/gateway/groups/{}/api_keys/register", path_args=[group_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_library_listings( - self, *, body: CreateLibraryListingRequest + self, *, request: CreateLibraryListingRequest ) -> LibraryListing: """Creates a new library listing""" return self._do_json( @@ -1993,14 +2186,18 @@ def post_library_listings( method="POST", path_fmt="/v1/library_listings", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_library_listings_versions( - self, *, user_defined_listing_id: str, body: CreateLibraryListingVersionRequest + self, + *, + user_defined_listing_id: str, + request: CreateLibraryListingVersionRequest, ) -> LibraryListingVersion: """Creates a new library listing version""" return self._do_json( @@ -2009,13 +2206,14 @@ def post_library_listings_versions( method="POST", path_fmt="/v1/library_listings/{}/versions", path_args=[user_defined_listing_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) - def post_llm_models(self, *, body: CreateLLMModelRequest) -> LLMModelHandle: + def post_llm_models(self, *, request: CreateLLMModelRequest) -> LLMModelHandle: """Creates a new BIS-LLM deployment""" return self._do_json( LLMModelHandle, @@ -2023,14 +2221,15 @@ def post_llm_models(self, *, body: CreateLLMModelRequest) -> LLMModelHandle: method="POST", path_fmt="/v1/llm_models", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_llm_models_deployments( - self, *, model_id: str, body: CreateLLMModelVersionRequest + self, *, model_id: str, request: CreateLLMModelVersionRequest ) -> LLMModelHandle: """Creates a new BIS-LLM deployment version""" return self._do_json( @@ -2039,14 +2238,15 @@ def post_llm_models_deployments( method="POST", path_fmt="/v1/llm_models/{}/deployments", path_args=[model_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_loops_checkpoints_validate( - self, *, body: ValidateLoopsCheckpointRequest + self, *, request: ValidateLoopsCheckpointRequest ) -> ValidateLoopsCheckpointResponse: """Validates a Loops checkpoint bt:// URI""" return self._do_json( @@ -2055,7 +2255,8 @@ def post_loops_checkpoints_validate( method="POST", path_fmt="/v1/loops/checkpoints/validate", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -2072,13 +2273,14 @@ def post_loops_deployments_deactivate( path_fmt="/v1/loops/deployments/{}/deactivate", path_args=[deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), ) def post_loops_deployments_metrics( - self, *, deployment_id: str, body: GetLoopsDeploymentMetricsRequest + self, *, deployment_id: str, request: GetLoopsDeploymentMetricsRequest ) -> GetLoopsDeploymentMetricsResponse: """Gets metrics for a Loops trainer deployment""" return self._do_json( @@ -2087,13 +2289,16 @@ def post_loops_deployments_metrics( method="POST", path_fmt="/v1/loops/deployments/{}/metrics", path_args=[deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) - def post_loops_runs(self, *, body: CreateLoopsRunRequest) -> CreateLoopsRunResponse: + def post_loops_runs( + self, *, request: CreateLoopsRunRequest + ) -> CreateLoopsRunResponse: """Creates a Loops run""" return self._do_json( CreateLoopsRunResponse, @@ -2101,14 +2306,15 @@ def post_loops_runs(self, *, body: CreateLoopsRunRequest) -> CreateLoopsRunRespo method="POST", path_fmt="/v1/loops/runs", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_loops_samplers( - self, *, body: CreateLoopsSamplerRequest + self, *, request: CreateLoopsSamplerRequest ) -> CreateLoopsSamplerResponse: """Creates a Loops sampler""" return self._do_json( @@ -2117,7 +2323,8 @@ def post_loops_samplers( method="POST", path_fmt="/v1/loops/samplers", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -2132,13 +2339,14 @@ def post_loops_sessions(self) -> CreateLoopsSessionResponse: path_fmt="/v1/loops/sessions", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), ) def post_model_apis_snapshots( - self, *, body: CreateModelWeightSnapshotRequest + self, *, request: CreateModelWeightSnapshotRequest ) -> ModelWeightSnapshot: """Creates a model weight snapshot""" return self._do_json( @@ -2147,14 +2355,15 @@ def post_model_apis_snapshots( method="POST", path_fmt="/v1/model_apis/snapshots", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_model_apis_snapshots_model_id( - self, *, model_id: str, body: CreateModelWeightSnapshotRequest + self, *, model_id: str, request: CreateModelWeightSnapshotRequest ) -> ModelWeightSnapshot: """Creates a model weight snapshot""" return self._do_json( @@ -2163,13 +2372,14 @@ def post_model_apis_snapshots_model_id( method="POST", path_fmt="/v1/model_apis/snapshots/{}", path_args=[model_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) - def post_models(self, *, body: CreateModelRequest) -> CreatedModelDeployment: + def post_models(self, *, request: CreateModelRequest) -> CreatedModelDeployment: """Creates a new model from a source""" return self._do_json( CreatedModelDeployment, @@ -2177,14 +2387,15 @@ def post_models(self, *, body: CreateModelRequest) -> CreatedModelDeployment: method="POST", path_fmt="/v1/models", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_models_deployments( - self, *, model_id: str, body: CreateModelDeploymentRequest + self, *, model_id: str, request: CreateModelDeploymentRequest ) -> CreatedModelDeployment: """Adds a new deployment to a model""" return self._do_json( @@ -2193,7 +2404,8 @@ def post_models_deployments( method="POST", path_fmt="/v1/models/{}/deployments", path_args=[model_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -2210,6 +2422,7 @@ def post_models_deployments_activate( path_fmt="/v1/models/{}/deployments/{}/activate", path_args=[model_id, deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2226,6 +2439,7 @@ def post_models_deployments_deactivate( path_fmt="/v1/models/{}/deployments/{}/deactivate", path_args=[model_id, deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2242,6 +2456,7 @@ def post_models_deployments_development_activate( path_fmt="/v1/models/{}/deployments/development/activate", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2258,13 +2473,14 @@ def post_models_deployments_development_deactivate( path_fmt="/v1/models/{}/deployments/development/deactivate", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), ) def post_models_deployments_development_promote( - self, *, model_id: str, body: PromoteRequest + self, *, model_id: str, request: PromoteRequest ) -> Deployment: """Promotes a development deployment to production""" return self._do_json( @@ -2273,7 +2489,8 @@ def post_models_deployments_development_promote( method="POST", path_fmt="/v1/models/{}/deployments/development/promote", path_args=[model_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -2290,13 +2507,14 @@ def post_models_deployments_development_retry( path_fmt="/v1/models/{}/deployments/development/retry", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), ) def post_models_deployments_logs( - self, *, model_id: str, deployment_id: str, body: GetDeploymentLogsRequest + self, *, model_id: str, deployment_id: str, request: GetDeploymentLogsRequest ) -> GetLogsResponse: """Gets the logs for a model deployment (deprecated; use GET)""" return self._do_json( @@ -2305,14 +2523,19 @@ def post_models_deployments_logs( method="POST", path_fmt="/v1/models/{}/deployments/{}/logs", path_args=[model_id, deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_models_deployments_patches( - self, *, model_id: str, deployment_id: str, body: CreateDeploymentPatchRequest + self, + *, + model_id: str, + deployment_id: str, + request: CreateDeploymentPatchRequest, ) -> CreateDeploymentPatchResponse: """Stages a patch against a development deployment""" return self._do_json( @@ -2321,14 +2544,19 @@ def post_models_deployments_patches( method="POST", path_fmt="/v1/models/{}/deployments/{}/patches", path_args=[model_id, deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_models_deployments_patches_sync( - self, *, model_id: str, deployment_id: str, body: SyncDeploymentPatchesRequest + self, + *, + model_id: str, + deployment_id: str, + request: SyncDeploymentPatchesRequest, ) -> SyncDeploymentPatchesResponse: """Syncs staged patches to a development deployment""" return self._do_json( @@ -2337,7 +2565,8 @@ def post_models_deployments_patches_sync( method="POST", path_fmt="/v1/models/{}/deployments/{}/patches/sync", path_args=[model_id, deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -2354,6 +2583,7 @@ def post_models_deployments_production_activate( path_fmt="/v1/models/{}/deployments/production/activate", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2370,6 +2600,7 @@ def post_models_deployments_production_deactivate( path_fmt="/v1/models/{}/deployments/production/deactivate", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2386,13 +2617,14 @@ def post_models_deployments_production_retry( path_fmt="/v1/models/{}/deployments/production/retry", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), ) def post_models_deployments_promote( - self, *, model_id: str, deployment_id: str, body: PromoteRequest + self, *, model_id: str, deployment_id: str, request: PromoteRequest ) -> Deployment: """Promotes a deployment to production""" return self._do_json( @@ -2401,7 +2633,8 @@ def post_models_deployments_promote( method="POST", path_fmt="/v1/models/{}/deployments/{}/promote", path_args=[model_id, deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -2418,13 +2651,14 @@ def post_models_deployments_retry( path_fmt="/v1/models/{}/deployments/{}/retry", path_args=[model_id, deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), ) def post_models_deployments_ssh_sign( - self, *, model_id: str, deployment_id: str, body: SignSSHCertificateRequest + self, *, model_id: str, deployment_id: str, request: SignSSHCertificateRequest ) -> SignSSHCertificateResponse: """Signs an SSH certificate for an inference model""" return self._do_json( @@ -2433,14 +2667,15 @@ def post_models_deployments_ssh_sign( method="POST", path_fmt="/v1/models/{}/deployments/{}/ssh/sign", path_args=[model_id, deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_models_environments( - self, *, model_id: str, body: CreateEnvironmentRequest + self, *, model_id: str, request: CreateEnvironmentRequest ) -> Environment: """Creates an environment""" return self._do_json( @@ -2449,7 +2684,8 @@ def post_models_environments( method="POST", path_fmt="/v1/models/{}/environments", path_args=[model_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -2466,6 +2702,7 @@ def post_models_environments_activate( path_fmt="/v1/models/{}/environments/{}/activate", path_args=[model_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2482,6 +2719,7 @@ def post_models_environments_cancel_promotion( path_fmt="/v1/models/{}/environments/{}/cancel_promotion", path_args=[model_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2498,6 +2736,7 @@ def post_models_environments_deactivate( path_fmt="/v1/models/{}/environments/{}/deactivate", path_args=[model_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2514,6 +2753,7 @@ def post_models_environments_force_cancel_promotion( path_fmt="/v1/models/{}/environments/{}/force_cancel_promotion", path_args=[model_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2530,6 +2770,7 @@ def post_models_environments_force_roll_forward_promotion( path_fmt="/v1/models/{}/environments/{}/force_roll_forward_promotion", path_args=[model_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2546,13 +2787,14 @@ def post_models_environments_pause_promotion( path_fmt="/v1/models/{}/environments/{}/pause_promotion", path_args=[model_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), ) def post_models_environments_promote( - self, *, model_id: str, env_name: str, body: PromoteToEnvironmentRequest + self, *, model_id: str, env_name: str, request: PromoteToEnvironmentRequest ) -> Deployment: """Promotes a deployment to an environment""" return self._do_json( @@ -2561,7 +2803,8 @@ def post_models_environments_promote( method="POST", path_fmt="/v1/models/{}/environments/{}/promote", path_args=[model_id, env_name], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -2578,13 +2821,14 @@ def post_models_environments_resume_promotion( path_fmt="/v1/models/{}/environments/{}/resume_promotion", path_args=[model_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), ) def post_prepare_model_upload( - self, *, body: PrepareModelUploadRequest + self, *, request: PrepareModelUploadRequest ) -> PrepareModelUploadResponse: """Validates a model push payload and issues upload credentials""" return self._do_json( @@ -2593,13 +2837,14 @@ def post_prepare_model_upload( method="POST", path_fmt="/v1/prepare_model_upload", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) - def post_secrets(self, *, body: UpsertSecretRequest) -> Secret: + def post_secrets(self, *, request: UpsertSecretRequest) -> Secret: """Upserts a secret""" return self._do_json( Secret, @@ -2607,13 +2852,16 @@ def post_secrets(self, *, body: UpsertSecretRequest) -> Secret: method="POST", path_fmt="/v1/secrets", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) - def post_teams_api_keys(self, *, team_id: str, body: CreateAPIKeyRequest) -> APIKey: + def post_teams_api_keys( + self, *, team_id: str, request: CreateAPIKeyRequest + ) -> APIKey: """Creates a team API key""" return self._do_json( APIKey, @@ -2621,14 +2869,15 @@ def post_teams_api_keys(self, *, team_id: str, body: CreateAPIKeyRequest) -> API method="POST", path_fmt="/v1/teams/{}/api_keys", path_args=[team_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_teams_llm_models( - self, *, team_id: str, body: CreateLLMModelRequest + self, *, team_id: str, request: CreateLLMModelRequest ) -> LLMModelHandle: """Creates a new BIS-LLM deployment""" return self._do_json( @@ -2637,14 +2886,15 @@ def post_teams_llm_models( method="POST", path_fmt="/v1/teams/{}/llm_models", path_args=[team_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_teams_models( - self, *, team_id: str, body: CreateModelRequest + self, *, team_id: str, request: CreateModelRequest ) -> CreatedModelDeployment: """Creates a new model from a source""" return self._do_json( @@ -2653,13 +2903,16 @@ def post_teams_models( method="POST", path_fmt="/v1/teams/{}/models", path_args=[team_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) - def post_teams_secrets(self, *, team_id: str, body: UpsertSecretRequest) -> Secret: + def post_teams_secrets( + self, *, team_id: str, request: UpsertSecretRequest + ) -> Secret: """Upserts a secret in a team""" return self._do_json( Secret, @@ -2667,14 +2920,15 @@ def post_teams_secrets(self, *, team_id: str, body: UpsertSecretRequest) -> Secr method="POST", path_fmt="/v1/teams/{}/secrets", path_args=[team_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_teams_training_projects( - self, *, team_id: str, body: UpsertTrainingProjectRequest + self, *, team_id: str, request: UpsertTrainingProjectRequest ) -> UpsertTrainingProjectResponse: """Upserts a training project in a specific team""" return self._do_json( @@ -2683,14 +2937,15 @@ def post_teams_training_projects( method="POST", path_fmt="/v1/teams/{}/training_projects", path_args=[team_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_training_jobs_search( - self, *, body: SearchTrainingJobsRequest + self, *, request: SearchTrainingJobsRequest ) -> SearchTrainingJobsResponse: """Searches training jobs""" return self._do_json( @@ -2699,14 +2954,15 @@ def post_training_jobs_search( method="POST", path_fmt="/v1/training_jobs/search", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_training_projects( - self, *, body: UpsertTrainingProjectRequest + self, *, request: UpsertTrainingProjectRequest ) -> UpsertTrainingProjectResponse: """Upserts a training project""" return self._do_json( @@ -2715,14 +2971,15 @@ def post_training_projects( method="POST", path_fmt="/v1/training_projects", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) def post_training_projects_jobs( - self, *, training_project_id: str, body: CreateTrainingJobRequest + self, *, training_project_id: str, request: CreateTrainingJobRequest ) -> CreateTrainingJobResponse: """Creates a training job""" return self._do_json( @@ -2731,7 +2988,8 @@ def post_training_projects_jobs( method="POST", path_fmt="/v1/training_projects/{}/jobs", path_args=[training_project_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -2742,7 +3000,7 @@ def post_training_projects_jobs_logs( *, training_project_id: str, training_job_id: str, - body: GetTrainingJobLogsRequest, + request: GetTrainingJobLogsRequest, ) -> GetLogsResponse: """Gets the logs for a training job (deprecated; use GET)""" return self._do_json( @@ -2751,7 +3009,8 @@ def post_training_projects_jobs_logs( method="POST", path_fmt="/v1/training_projects/{}/jobs/{}/logs", path_args=[training_project_id, training_job_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -2762,7 +3021,7 @@ def post_training_projects_jobs_metrics( *, training_project_id: str, training_job_id: str, - body: GetTrainingJobMetricsRequest, + request: GetTrainingJobMetricsRequest, ) -> GetTrainingJobMetricsResponse: """Gets the metrics for a training job (deprecated; use GET)""" return self._do_json( @@ -2771,7 +3030,8 @@ def post_training_projects_jobs_metrics( method="POST", path_fmt="/v1/training_projects/{}/jobs/{}/metrics", path_args=[training_project_id, training_job_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -2788,6 +3048,7 @@ def post_training_projects_jobs_recreate( path_fmt="/v1/training_projects/{}/jobs/{}/recreate", path_args=[training_project_id, training_job_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2798,7 +3059,7 @@ def post_training_projects_jobs_ssh_sign( *, training_project_id: str, training_job_id: str, - body: SignSSHCertificateRequest, + request: SignSSHCertificateRequest, ) -> SignSSHCertificateResponse: """Signs an SSH certificate for a training job""" return self._do_json( @@ -2807,7 +3068,8 @@ def post_training_projects_jobs_ssh_sign( method="POST", path_fmt="/v1/training_projects/{}/jobs/{}/ssh/sign", path_args=[training_project_id, training_job_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -2818,7 +3080,7 @@ def post_training_projects_jobs_stop( *, training_project_id: str, training_job_id: str, - body: StopTrainingJobRequest, + request: StopTrainingJobRequest, ) -> StopTrainingJobResponse: """Stops a training job""" return self._do_json( @@ -2827,7 +3089,8 @@ def post_training_projects_jobs_stop( method="POST", path_fmt="/v1/training_projects/{}/jobs/{}/stop", path_args=[training_project_id, training_job_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -2840,10 +3103,25 @@ def _do(self, request: _ApiRequest) -> httpx.Response: json_body = None if request.body is not None: if isinstance(request.body, BaseModel): - json_body = request.body.model_dump(mode="json") + # Only fields the caller set are sent, so unset fields fall + # back to the server default rather than being reset here. + # An explicit None is kept, since null can mean "clear". + json_body = request.body.model_dump(mode="json", exclude_unset=True) else: json_body = request.body - response = self._http_client.request(request.method, path, json=json_body) + params = None + if request.query is not None: + if isinstance(request.query, BaseModel): + # As above, plus dropping None: a null query parameter is + # meaningless and would otherwise serialize as an empty string. + params = request.query.model_dump( + mode="json", exclude_unset=True, exclude_none=True + ) + else: + params = request.query + response = self._http_client.request( + request.method, path, json=json_body, params=params + ) if response.status_code != request.success_code: raise ResponseError(status_code=response.status_code, body=response.text) return response @@ -2879,6 +3157,7 @@ async def delete_api_keys(self, *, api_key_prefix: str) -> APIKeyTombstone: path_fmt="/v1/api_keys/{}", path_args=[api_key_prefix], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2893,6 +3172,7 @@ async def delete_chains(self, *, chain_id: str) -> ChainTombstone: path_fmt="/v1/chains/{}", path_args=[chain_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2909,6 +3189,7 @@ async def delete_chains_deployments( path_fmt="/v1/chains/{}/deployments/{}", path_args=[chain_id, chain_deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2923,6 +3204,7 @@ async def delete_gateway_endpoints(self, *, endpoint_id: str) -> EndpointTombsto path_fmt="/v1/gateway/endpoints/{}", path_args=[endpoint_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2939,6 +3221,7 @@ async def delete_library_listings( path_fmt="/v1/library_listings/{}", path_args=[user_defined_listing_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2955,6 +3238,7 @@ async def delete_library_listings_versions( path_fmt="/v1/library_listings/{}/versions/{}", path_args=[user_defined_listing_id, version_tag], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2969,6 +3253,7 @@ async def delete_models(self, *, model_id: str) -> ModelTombstone: path_fmt="/v1/models/{}", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -2985,6 +3270,7 @@ async def delete_models_deployments( path_fmt="/v1/models/{}/deployments/{}", path_args=[model_id, deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3001,6 +3287,7 @@ async def delete_models_deployments_replicas( path_fmt="/v1/models/{}/deployments/{}/replicas/{}", path_args=[model_id, deployment_id, replica_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3015,6 +3302,7 @@ async def delete_secrets(self, *, secret_name: str) -> SecretTombstone: path_fmt="/v1/secrets/{}", path_args=[secret_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3031,6 +3319,7 @@ async def delete_teams_secrets( path_fmt="/v1/teams/{}/secrets/{}", path_args=[team_id, secret_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3047,6 +3336,7 @@ async def delete_training_projects( path_fmt="/v1/training_projects/{}", path_args=[training_project_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3063,6 +3353,7 @@ async def delete_training_projects_jobs( path_fmt="/v1/training_projects/{}/jobs/{}", path_args=[training_project_id, training_job_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3077,12 +3368,15 @@ async def get_api_keys(self) -> APIKeys: path_fmt="/v1/api_keys", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), ) - async def get_billing_usage_summary(self) -> UsageSummary: + async def get_billing_usage_summary( + self, *, request: GetBillingUsageSummaryRequest + ) -> UsageSummary: """Gets billing usage summary for a date range""" return await self._do_json( UsageSummary, @@ -3091,6 +3385,7 @@ async def get_billing_usage_summary(self) -> UsageSummary: path_fmt="/v1/billing/usage_summary", path_args=[], body=None, + query=request, success_code=200, error_codes=None, ), @@ -3105,6 +3400,7 @@ async def get_blobs_credentials_model(self) -> GetBlobCredentialsResponse: path_fmt="/v1/blobs/credentials/model", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3119,6 +3415,7 @@ async def get_blobs_credentials_train(self) -> GetBlobCredentialsResponse: path_fmt="/v1/blobs/credentials/train", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3133,6 +3430,7 @@ async def get_chains(self) -> Chains: path_fmt="/v1/chains", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3147,6 +3445,7 @@ async def get_chains_chain_id(self, *, chain_id: str) -> Chain: path_fmt="/v1/chains/{}", path_args=[chain_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3161,6 +3460,7 @@ async def get_chains_deployments(self, *, chain_id: str) -> ChainDeployments: path_fmt="/v1/chains/{}/deployments", path_args=[chain_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3177,13 +3477,19 @@ async def get_chains_deployments_chain_deployment_id( path_fmt="/v1/chains/{}/deployments/{}", path_args=[chain_id, chain_deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), ) async def get_chains_deployments_chainlets_logs( - self, *, chain_id: str, chain_deployment_id: str, chainlet_id: str + self, + *, + chain_id: str, + chain_deployment_id: str, + chainlet_id: str, + request: GetChainsDeploymentsChainletsLogsRequest | None = None, ) -> GetLogsResponse: """Gets the logs for a chainlet within a chain deployment""" return await self._do_json( @@ -3193,6 +3499,7 @@ async def get_chains_deployments_chainlets_logs( path_fmt="/v1/chains/{}/deployments/{}/chainlets/{}/logs", path_args=[chain_id, chain_deployment_id, chainlet_id], body=None, + query=request, success_code=200, error_codes=None, ), @@ -3207,6 +3514,7 @@ async def get_chains_environments(self, *, chain_id: str) -> Environments: path_fmt="/v1/chains/{}/environments", path_args=[chain_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3223,6 +3531,7 @@ async def get_chains_environments_env_name( path_fmt="/v1/chains/{}/environments/{}", path_args=[chain_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3237,6 +3546,7 @@ async def get_environment_groups(self) -> EnvironmentGroups: path_fmt="/v1/environment_groups", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3253,6 +3563,7 @@ async def get_environment_groups_env_name( path_fmt="/v1/environment_groups/{}", path_args=[env_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3267,6 +3578,7 @@ async def get_gateway_endpoints(self) -> EndpointsResponse: path_fmt="/v1/gateway/endpoints", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3281,6 +3593,7 @@ async def get_gateway_endpoints_endpoint_id(self, *, endpoint_id: str) -> Endpoi path_fmt="/v1/gateway/endpoints/{}", path_args=[endpoint_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3295,6 +3608,7 @@ async def get_gateway_groups(self) -> GroupsResponse: path_fmt="/v1/gateway/groups", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3311,6 +3625,7 @@ async def get_gateway_groups_api_keys( path_fmt="/v1/gateway/groups/{}/api_keys", path_args=[group_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3327,6 +3642,7 @@ async def get_gateway_groups_api_keys_api_key_prefix( path_fmt="/v1/gateway/groups/{}/api_keys/{}", path_args=[group_id, api_key_prefix], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3341,6 +3657,7 @@ async def get_gateway_groups_group_id(self, *, group_id: str) -> Group: path_fmt="/v1/gateway/groups/{}", path_args=[group_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3355,6 +3672,7 @@ async def get_instance_type_prices(self) -> InstanceTypePrices: path_fmt="/v1/instance_type_prices", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3369,6 +3687,7 @@ async def get_instance_types(self) -> InstanceTypes: path_fmt="/v1/instance_types", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3383,6 +3702,7 @@ async def get_library_listings(self) -> LibraryListings: path_fmt="/v1/library_listings", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3399,6 +3719,7 @@ async def get_library_listings_user_defined_listing_id( path_fmt="/v1/library_listings/{}", path_args=[user_defined_listing_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3415,6 +3736,7 @@ async def get_library_listings_versions( path_fmt="/v1/library_listings/{}/versions", path_args=[user_defined_listing_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3431,6 +3753,7 @@ async def get_library_listings_versions_version_tag( path_fmt="/v1/library_listings/{}/versions/{}", path_args=[user_defined_listing_id, version_tag], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3445,12 +3768,15 @@ async def get_loops_capabilities(self) -> GetLoopsCapabilitiesResponse: path_fmt="/v1/loops/capabilities", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), ) - async def get_loops_checkpoints(self) -> ListLoopsCheckpointsResponse: + async def get_loops_checkpoints( + self, *, request: GetLoopsCheckpointsRequest | None = None + ) -> ListLoopsCheckpointsResponse: """Lists Loops checkpoints""" return await self._do_json( ListLoopsCheckpointsResponse, @@ -3459,6 +3785,7 @@ async def get_loops_checkpoints(self) -> ListLoopsCheckpointsResponse: path_fmt="/v1/loops/checkpoints", path_args=[], body=None, + query=request, success_code=200, error_codes=None, ), @@ -3475,6 +3802,7 @@ async def get_loops_checkpoints_files( path_fmt="/v1/loops/checkpoints/{}/files", path_args=[checkpoint_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3489,6 +3817,7 @@ async def get_loops_deployments(self) -> ListLoopsDeploymentsResponse: path_fmt="/v1/loops/deployments", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3505,13 +3834,17 @@ async def get_loops_deployments_deployment_id( path_fmt="/v1/loops/deployments/{}", path_args=[deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), ) async def get_loops_deployments_logs( - self, *, deployment_id: str + self, + *, + deployment_id: str, + request: GetLoopsDeploymentsLogsRequest | None = None, ) -> GetLogsResponse: """Gets logs for a Loops trainer deployment""" return await self._do_json( @@ -3521,12 +3854,15 @@ async def get_loops_deployments_logs( path_fmt="/v1/loops/deployments/{}/logs", path_args=[deployment_id], body=None, + query=request, success_code=200, error_codes=None, ), ) - async def get_loops_runs(self) -> ListLoopsRunsResponse: + async def get_loops_runs( + self, *, request: GetLoopsRunsRequest | None = None + ) -> ListLoopsRunsResponse: """Lists Loops runs""" return await self._do_json( ListLoopsRunsResponse, @@ -3535,6 +3871,7 @@ async def get_loops_runs(self) -> ListLoopsRunsResponse: path_fmt="/v1/loops/runs", path_args=[], body=None, + query=request, success_code=200, error_codes=None, ), @@ -3549,6 +3886,7 @@ async def get_loops_runs_run_id(self, *, run_id: str) -> GetLoopsRunResponse: path_fmt="/v1/loops/runs/{}", path_args=[run_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3563,6 +3901,7 @@ async def get_loops_samplers(self) -> ListLoopsSamplersResponse: path_fmt="/v1/loops/samplers", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3579,6 +3918,7 @@ async def get_loops_samplers_sampler_id( path_fmt="/v1/loops/samplers/{}", path_args=[sampler_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3593,6 +3933,7 @@ async def get_loops_sessions(self, *, session_id: str) -> GetLoopsSessionRespons path_fmt="/v1/loops/sessions/{}", path_args=[session_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3607,12 +3948,15 @@ async def get_loops_user_config(self) -> GetLoopsUserConfigResponse: path_fmt="/v1/loops/user_config", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), ) - async def get_model_apis(self) -> ModelAPIsResponse: + async def get_model_apis( + self, *, request: GetModelApisRequest | None = None + ) -> ModelAPIsResponse: """Lists Model APIs""" return await self._do_json( ModelAPIsResponse, @@ -3621,6 +3965,7 @@ async def get_model_apis(self) -> ModelAPIsResponse: path_fmt="/v1/model_apis", path_args=[], body=None, + query=request, success_code=200, error_codes=None, ), @@ -3635,6 +3980,7 @@ async def get_model_apis_model_api_name(self, *, model_api_name: str) -> ModelAP path_fmt="/v1/model_apis/{}", path_args=[model_api_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3649,6 +3995,7 @@ async def get_model_apis_snapshots(self) -> ModelWeightSnapshot: path_fmt="/v1/model_apis/snapshots", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3665,12 +4012,13 @@ async def get_model_apis_snapshots_model_id( path_fmt="/v1/model_apis/snapshots/{}", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), ) - async def get_models(self) -> Models: + async def get_models(self, *, request: GetModelsRequest | None = None) -> Models: """Gets all models""" return await self._do_json( Models, @@ -3679,12 +4027,15 @@ async def get_models(self) -> Models: path_fmt="/v1/models", path_args=[], body=None, + query=request, success_code=200, error_codes=None, ), ) - async def get_models_deployments(self, *, model_id: str) -> Deployments: + async def get_models_deployments( + self, *, model_id: str, request: GetModelsDeploymentsRequest | None = None + ) -> Deployments: """Gets all deployments of a model""" return await self._do_json( Deployments, @@ -3693,13 +4044,18 @@ async def get_models_deployments(self, *, model_id: str) -> Deployments: path_fmt="/v1/models/{}/deployments", path_args=[model_id], body=None, + query=request, success_code=200, error_codes=None, ), ) async def get_models_deployments_config( - self, *, model_id: str, deployment_id: str + self, + *, + model_id: str, + deployment_id: str, + request: GetModelsDeploymentsConfigRequest | None = None, ) -> DeploymentConfigResponse: """Gets a deployment's config""" return await self._do_json( @@ -3709,6 +4065,7 @@ async def get_models_deployments_config( path_fmt="/v1/models/{}/deployments/{}/config", path_args=[model_id, deployment_id], body=None, + query=request, success_code=200, error_codes=None, ), @@ -3725,6 +4082,7 @@ async def get_models_deployments_deployment_id( path_fmt="/v1/models/{}/deployments/{}", path_args=[model_id, deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3739,6 +4097,7 @@ async def get_models_deployments_development(self, *, model_id: str) -> Deployme path_fmt="/v1/models/{}/deployments/development", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3755,13 +4114,18 @@ async def get_models_deployments_download( path_fmt="/v1/models/{}/deployments/{}/download", path_args=[model_id, deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), ) async def get_models_deployments_logs( - self, *, model_id: str, deployment_id: str + self, + *, + model_id: str, + deployment_id: str, + request: GetModelsDeploymentsLogsRequest | None = None, ) -> GetLogsResponse: """Gets the logs for a model deployment""" return await self._do_json( @@ -3771,13 +4135,18 @@ async def get_models_deployments_logs( path_fmt="/v1/models/{}/deployments/{}/logs", path_args=[model_id, deployment_id], body=None, + query=request, success_code=200, error_codes=None, ), ) async def get_models_deployments_metrics( - self, *, model_id: str, deployment_id: str + self, + *, + model_id: str, + deployment_id: str, + request: GetModelsDeploymentsMetricsRequest | None = None, ) -> GetModelMetricsResponse: """Gets the metrics for a model deployment""" return await self._do_json( @@ -3787,6 +4156,7 @@ async def get_models_deployments_metrics( path_fmt="/v1/models/{}/deployments/{}/metrics", path_args=[model_id, deployment_id], body=None, + query=request, success_code=200, error_codes=None, ), @@ -3803,6 +4173,7 @@ async def get_models_deployments_patches_state( path_fmt="/v1/models/{}/deployments/{}/patches/state", path_args=[model_id, deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3817,6 +4188,7 @@ async def get_models_deployments_production(self, *, model_id: str) -> Deploymen path_fmt="/v1/models/{}/deployments/production", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3831,6 +4203,7 @@ async def get_models_environments(self, *, model_id: str) -> Environments: path_fmt="/v1/models/{}/environments", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3847,13 +4220,18 @@ async def get_models_environments_env_name( path_fmt="/v1/models/{}/environments/{}", path_args=[model_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), ) async def get_models_environments_logs( - self, *, model_id: str, env_name: str + self, + *, + model_id: str, + env_name: str, + request: GetModelsEnvironmentsLogsRequest | None = None, ) -> GetLogsResponse: """Gets the logs for a model environment""" return await self._do_json( @@ -3863,13 +4241,18 @@ async def get_models_environments_logs( path_fmt="/v1/models/{}/environments/{}/logs", path_args=[model_id, env_name], body=None, + query=request, success_code=200, error_codes=None, ), ) async def get_models_environments_metrics( - self, *, model_id: str, env_name: str + self, + *, + model_id: str, + env_name: str, + request: GetModelsEnvironmentsMetricsRequest | None = None, ) -> GetModelMetricsResponse: """Gets the metrics for a model environment.""" return await self._do_json( @@ -3879,6 +4262,7 @@ async def get_models_environments_metrics( path_fmt="/v1/models/{}/environments/{}/metrics", path_args=[model_id, env_name], body=None, + query=request, success_code=200, error_codes=None, ), @@ -3893,6 +4277,7 @@ async def get_models_model_id(self, *, model_id: str) -> Model: path_fmt="/v1/models/{}", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3907,12 +4292,13 @@ async def get_secrets(self) -> Secrets: path_fmt="/v1/secrets", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), ) - async def get_teams(self) -> Teams: + async def get_teams(self, *, request: GetTeamsRequest | None = None) -> Teams: """Lists all teams""" return await self._do_json( Teams, @@ -3921,6 +4307,7 @@ async def get_teams(self) -> Teams: path_fmt="/v1/teams", path_args=[], body=None, + query=request, success_code=200, error_codes=None, ), @@ -3935,6 +4322,7 @@ async def get_teams_environment_groups(self, *, team_id: str) -> EnvironmentGrou path_fmt="/v1/teams/{}/environment_groups", path_args=[team_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3951,12 +4339,15 @@ async def get_teams_environment_groups_env_name( path_fmt="/v1/teams/{}/environment_groups/{}", path_args=[team_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), ) - async def get_teams_models(self, *, team_id: str) -> Models: + async def get_teams_models( + self, *, team_id: str, request: GetTeamsModelsRequest | None = None + ) -> Models: """Gets all models""" return await self._do_json( Models, @@ -3965,6 +4356,7 @@ async def get_teams_models(self, *, team_id: str) -> Models: path_fmt="/v1/teams/{}/models", path_args=[team_id], body=None, + query=request, success_code=200, error_codes=None, ), @@ -3979,6 +4371,7 @@ async def get_teams_secrets(self, *, team_id: str) -> Secrets: path_fmt="/v1/teams/{}/secrets", path_args=[team_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -3993,6 +4386,7 @@ async def get_teams_team_id(self, *, team_id: str) -> Team: path_fmt="/v1/teams/{}", path_args=[team_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -4007,6 +4401,7 @@ async def get_training_capacity(self) -> GetTrainingGpuCapacityResponse: path_fmt="/v1/training/capacity", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -4023,6 +4418,7 @@ async def get_training_jobs_queue_context( path_fmt="/v1/training/jobs/{}/queue_context", path_args=[training_job_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -4037,6 +4433,7 @@ async def get_training_projects(self) -> ListTrainingProjectsResponse: path_fmt="/v1/training_projects", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -4053,6 +4450,7 @@ async def get_training_projects_cache_summary( path_fmt="/v1/training_projects/{}/cache/summary", path_args=[training_project_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -4069,6 +4467,7 @@ async def get_training_projects_jobs( path_fmt="/v1/training_projects/{}/jobs", path_args=[training_project_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -4085,13 +4484,18 @@ async def get_training_projects_jobs_auth_codes( path_fmt="/v1/training_projects/{}/jobs/{}/auth_codes", path_args=[training_project_id, training_job_id], body=None, + query=None, success_code=200, error_codes=None, ), ) async def get_training_projects_jobs_checkpoint_files( - self, *, training_project_id: str, training_job_id: str + self, + *, + training_project_id: str, + training_job_id: str, + request: GetTrainingProjectsJobsCheckpointFilesRequest | None = None, ) -> GetTrainingJobCheckpointFilesResponse: """Gets training job checkpoint files""" return await self._do_json( @@ -4101,6 +4505,7 @@ async def get_training_projects_jobs_checkpoint_files( path_fmt="/v1/training_projects/{}/jobs/{}/checkpoint_files", path_args=[training_project_id, training_job_id], body=None, + query=request, success_code=200, error_codes=None, ), @@ -4117,6 +4522,7 @@ async def get_training_projects_jobs_checkpoints( path_fmt="/v1/training_projects/{}/jobs/{}/checkpoints", path_args=[training_project_id, training_job_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -4133,13 +4539,18 @@ async def get_training_projects_jobs_download( path_fmt="/v1/training_projects/{}/jobs/{}/download", path_args=[training_project_id, training_job_id], body=None, + query=None, success_code=200, error_codes=None, ), ) async def get_training_projects_jobs_logs( - self, *, training_project_id: str, training_job_id: str + self, + *, + training_project_id: str, + training_job_id: str, + request: GetTrainingProjectsJobsLogsRequest | None = None, ) -> GetLogsResponse: """Gets the logs for a training job""" return await self._do_json( @@ -4149,13 +4560,18 @@ async def get_training_projects_jobs_logs( path_fmt="/v1/training_projects/{}/jobs/{}/logs", path_args=[training_project_id, training_job_id], body=None, + query=request, success_code=200, error_codes=None, ), ) async def get_training_projects_jobs_metrics( - self, *, training_project_id: str, training_job_id: str + self, + *, + training_project_id: str, + training_job_id: str, + request: GetTrainingProjectsJobsMetricsRequest | None = None, ) -> GetTrainingJobMetricsResponse: """Gets the metrics for a training job""" return await self._do_json( @@ -4165,6 +4581,7 @@ async def get_training_projects_jobs_metrics( path_fmt="/v1/training_projects/{}/jobs/{}/metrics", path_args=[training_project_id, training_job_id], body=None, + query=request, success_code=200, error_codes=None, ), @@ -4181,6 +4598,7 @@ async def get_training_projects_jobs_training_job_id( path_fmt="/v1/training_projects/{}/jobs/{}", path_args=[training_project_id, training_job_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -4197,12 +4615,15 @@ async def get_training_projects_training_project_id( path_fmt="/v1/training_projects/{}", path_args=[training_project_id], body=None, + query=None, success_code=200, error_codes=None, ), ) - async def get_users(self) -> UsersResponse: + async def get_users( + self, *, request: GetUsersRequest | None = None + ) -> UsersResponse: """Lists users in the workspace""" return await self._do_json( UsersResponse, @@ -4211,6 +4632,7 @@ async def get_users(self) -> UsersResponse: path_fmt="/v1/users", path_args=[], body=None, + query=request, success_code=200, error_codes=None, ), @@ -4225,6 +4647,7 @@ async def get_users_me(self) -> UserInfo: path_fmt="/v1/users/me", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), @@ -4239,13 +4662,14 @@ async def get_users_user_id(self, *, user_id: str) -> UserInfo: path_fmt="/v1/users/{}", path_args=[user_id], body=None, + query=None, success_code=200, error_codes=None, ), ) async def patch_chains_environments( - self, *, chain_id: str, env_name: str, body: UpdateChainEnvironmentRequest + self, *, chain_id: str, env_name: str, request: UpdateChainEnvironmentRequest ) -> UpdateChainEnvironmentResponse: """Updates a chain environment's settings""" return await self._do_json( @@ -4254,7 +4678,8 @@ async def patch_chains_environments( method="PATCH", path_fmt="/v1/chains/{}/environments/{}", path_args=[chain_id, env_name], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -4265,7 +4690,7 @@ async def patch_chains_environments_chainlet_settings_autoscaling_settings( *, chain_id: str, env_name: str, - body: UpdateChainletEnvironmentAutoscalingSettingsRequest, + request: UpdateChainletEnvironmentAutoscalingSettingsRequest, ) -> UpdateAutoscalingSettingsResponse: """Updates a chainlet environment's autoscaling settings""" return await self._do_json( @@ -4274,14 +4699,15 @@ async def patch_chains_environments_chainlet_settings_autoscaling_settings( method="PATCH", path_fmt="/v1/chains/{}/environments/{}/chainlet_settings/autoscaling_settings", path_args=[chain_id, env_name], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def patch_environment_groups( - self, *, env_name: str, body: UpdateEnvironmentGroupRequest + self, *, env_name: str, request: UpdateEnvironmentGroupRequest ) -> EnvironmentGroup: """Updates an environment group's restriction settings""" return await self._do_json( @@ -4290,14 +4716,15 @@ async def patch_environment_groups( method="PATCH", path_fmt="/v1/environment_groups/{}", path_args=[env_name], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def patch_gateway_endpoints( - self, *, endpoint_id: str, body: UpdateEndpointRequest + self, *, endpoint_id: str, request: UpdateEndpointRequest ) -> Endpoint: """Updates a Gateway endpoint""" return await self._do_json( @@ -4306,14 +4733,15 @@ async def patch_gateway_endpoints( method="PATCH", path_fmt="/v1/gateway/endpoints/{}", path_args=[endpoint_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def patch_gateway_groups( - self, *, group_id: str, body: UpdateGroupRequest + self, *, group_id: str, request: UpdateGroupRequest ) -> Group: """Updates a group""" return await self._do_json( @@ -4322,14 +4750,15 @@ async def patch_gateway_groups( method="PATCH", path_fmt="/v1/gateway/groups/{}", path_args=[group_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def patch_library_listings( - self, *, user_defined_listing_id: str, body: UpdateLibraryListingRequest + self, *, user_defined_listing_id: str, request: UpdateLibraryListingRequest ) -> LibraryListing: """Updates a library listing""" return await self._do_json( @@ -4338,7 +4767,8 @@ async def patch_library_listings( method="PATCH", path_fmt="/v1/library_listings/{}", path_args=[user_defined_listing_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -4349,7 +4779,7 @@ async def patch_library_listings_versions( *, user_defined_listing_id: str, version_tag: str, - body: UpdateLibraryListingVersionRequest, + request: UpdateLibraryListingVersionRequest, ) -> LibraryListingVersion: """Updates a library listing version""" return await self._do_json( @@ -4358,14 +4788,15 @@ async def patch_library_listings_versions( method="PATCH", path_fmt="/v1/library_listings/{}/versions/{}", path_args=[user_defined_listing_id, version_tag], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def patch_loops_user_config( - self, *, body: PatchLoopsUserConfigRequest + self, *, request: PatchLoopsUserConfigRequest ) -> PatchLoopsUserConfigResponse: """Patches the caller's Loops user config""" return await self._do_json( @@ -4374,14 +4805,15 @@ async def patch_loops_user_config( method="PATCH", path_fmt="/v1/loops/user_config", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def patch_models_deployments_autoscaling_settings( - self, *, model_id: str, deployment_id: str, body: UpdateAutoscalingSettings + self, *, model_id: str, deployment_id: str, request: UpdateAutoscalingSettings ) -> UpdateAutoscalingSettingsResponse: """Updates a deployment's autoscaling settings""" return await self._do_json( @@ -4390,14 +4822,15 @@ async def patch_models_deployments_autoscaling_settings( method="PATCH", path_fmt="/v1/models/{}/deployments/{}/autoscaling_settings", path_args=[model_id, deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def patch_models_deployments_development_autoscaling_settings( - self, *, model_id: str, body: UpdateAutoscalingSettings + self, *, model_id: str, request: UpdateAutoscalingSettings ) -> UpdateAutoscalingSettingsResponse: """Updates a development deployment's autoscaling settings""" return await self._do_json( @@ -4406,14 +4839,15 @@ async def patch_models_deployments_development_autoscaling_settings( method="PATCH", path_fmt="/v1/models/{}/deployments/development/autoscaling_settings", path_args=[model_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def patch_models_deployments_production_autoscaling_settings( - self, *, model_id: str, body: UpdateAutoscalingSettings + self, *, model_id: str, request: UpdateAutoscalingSettings ) -> UpdateAutoscalingSettingsResponse: """Updates a production deployment's autoscaling settings""" return await self._do_json( @@ -4422,14 +4856,15 @@ async def patch_models_deployments_production_autoscaling_settings( method="PATCH", path_fmt="/v1/models/{}/deployments/production/autoscaling_settings", path_args=[model_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def patch_models_environments( - self, *, model_id: str, env_name: str, body: UpdateEnvironmentRequest + self, *, model_id: str, env_name: str, request: UpdateEnvironmentRequest ) -> UpdateAutoscalingSettingsResponse: """Updates an environment's settings""" return await self._do_json( @@ -4438,14 +4873,15 @@ async def patch_models_environments( method="PATCH", path_fmt="/v1/models/{}/environments/{}", path_args=[model_id, env_name], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def patch_teams_environment_groups( - self, *, team_id: str, env_name: str, body: UpdateEnvironmentGroupRequest + self, *, team_id: str, env_name: str, request: UpdateEnvironmentGroupRequest ) -> EnvironmentGroup: """Updates an environment group's restriction settings""" return await self._do_json( @@ -4454,14 +4890,15 @@ async def patch_teams_environment_groups( method="PATCH", path_fmt="/v1/teams/{}/environment_groups/{}", path_args=[team_id, env_name], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def patch_training_capacity( - self, *, body: PatchTeamTrainingGpuCapacityRequest + self, *, request: PatchTeamTrainingGpuCapacityRequest ) -> PatchTeamTrainingGpuCapacityResponse: """Sets a team's training GPU capacity""" return await self._do_json( @@ -4470,7 +4907,8 @@ async def patch_training_capacity( method="PATCH", path_fmt="/v1/training/capacity", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -4481,7 +4919,7 @@ async def patch_training_projects_jobs( *, training_project_id: str, training_job_id: str, - body: UpdateTrainingJobRequest, + request: UpdateTrainingJobRequest, ) -> UpdateTrainingJobResponse: """Updates a training job""" return await self._do_json( @@ -4490,7 +4928,8 @@ async def patch_training_projects_jobs( method="PATCH", path_fmt="/v1/training_projects/{}/jobs/{}", path_args=[training_project_id, training_job_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -4502,7 +4941,7 @@ async def patch_training_projects_jobs_interactive_sessions( training_project_id: str, training_job_id: str, session_id: str, - body: PatchInteractiveSessionRequest, + request: PatchInteractiveSessionRequest, ) -> PatchInteractiveSessionResponse: """Patches an interactive session""" return await self._do_json( @@ -4511,13 +4950,14 @@ async def patch_training_projects_jobs_interactive_sessions( method="PATCH", path_fmt="/v1/training_projects/{}/jobs/{}/interactive_sessions/{}", path_args=[training_project_id, training_job_id, session_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) - async def post_api_keys(self, *, body: CreateAPIKeyRequest) -> APIKey: + async def post_api_keys(self, *, request: CreateAPIKeyRequest) -> APIKey: """Creates an API key""" return await self._do_json( APIKey, @@ -4525,7 +4965,8 @@ async def post_api_keys(self, *, body: CreateAPIKeyRequest) -> APIKey: method="POST", path_fmt="/v1/api_keys", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -4542,13 +4983,14 @@ async def post_chains_deployments_deactivate( path_fmt="/v1/chains/{}/deployments/{}/deactivate", path_args=[chain_id, chain_deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), ) async def post_chains_environments( - self, *, chain_id: str, body: CreateChainEnvironmentRequest + self, *, chain_id: str, request: CreateChainEnvironmentRequest ) -> ChainEnvironment: """Creates a chain environment""" return await self._do_json( @@ -4557,7 +4999,8 @@ async def post_chains_environments( method="POST", path_fmt="/v1/chains/{}/environments", path_args=[chain_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -4568,7 +5011,7 @@ async def post_chains_environments_chainlet_settings_instance_types_update( *, chain_id: str, env_name: str, - body: UpdateChainletEnvironmentInstanceTypeRequest, + request: UpdateChainletEnvironmentInstanceTypeRequest, ) -> UpdateChainletEnvironmentInstanceTypeResponse: """Updates a chainlet environment's instance type settings""" return await self._do_json( @@ -4577,14 +5020,15 @@ async def post_chains_environments_chainlet_settings_instance_types_update( method="POST", path_fmt="/v1/chains/{}/environments/{}/chainlet_settings/instance_types/update", path_args=[chain_id, env_name], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_chains_environments_promote( - self, *, chain_id: str, env_name: str, body: PromoteToChainEnvironmentRequest + self, *, chain_id: str, env_name: str, request: PromoteToChainEnvironmentRequest ) -> ChainDeployment: """Promotes a chain deployment to an environment""" return await self._do_json( @@ -4593,13 +5037,16 @@ async def post_chains_environments_promote( method="POST", path_fmt="/v1/chains/{}/environments/{}/promote", path_args=[chain_id, env_name], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) - async def post_gateway_endpoints(self, *, body: CreateEndpointRequest) -> Endpoint: + async def post_gateway_endpoints( + self, *, request: CreateEndpointRequest + ) -> Endpoint: """Creates a Gateway endpoint""" return await self._do_json( Endpoint, @@ -4607,13 +5054,14 @@ async def post_gateway_endpoints(self, *, body: CreateEndpointRequest) -> Endpoi method="POST", path_fmt="/v1/gateway/endpoints", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) - async def post_gateway_groups(self, *, body: CreateGroupRequest) -> Group: + async def post_gateway_groups(self, *, request: CreateGroupRequest) -> Group: """Creates a group""" return await self._do_json( Group, @@ -4621,14 +5069,15 @@ async def post_gateway_groups(self, *, body: CreateGroupRequest) -> Group: method="POST", path_fmt="/v1/gateway/groups", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_gateway_groups_api_keys( - self, *, group_id: str, body: CreateApiKeyForGroupRequest + self, *, group_id: str, request: CreateApiKeyForGroupRequest ) -> CreateApiKeyForGroupResponse: """Creates an API key for a group""" return await self._do_json( @@ -4637,14 +5086,15 @@ async def post_gateway_groups_api_keys( method="POST", path_fmt="/v1/gateway/groups/{}/api_keys", path_args=[group_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_gateway_groups_api_keys_register( - self, *, group_id: str, body: RegisterAPIKeyRequest + self, *, group_id: str, request: RegisterAPIKeyRequest ) -> RegisterAPIKeyResponse: """Registers an API key for a group""" return await self._do_json( @@ -4653,14 +5103,15 @@ async def post_gateway_groups_api_keys_register( method="POST", path_fmt="/v1/gateway/groups/{}/api_keys/register", path_args=[group_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_library_listings( - self, *, body: CreateLibraryListingRequest + self, *, request: CreateLibraryListingRequest ) -> LibraryListing: """Creates a new library listing""" return await self._do_json( @@ -4669,14 +5120,18 @@ async def post_library_listings( method="POST", path_fmt="/v1/library_listings", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_library_listings_versions( - self, *, user_defined_listing_id: str, body: CreateLibraryListingVersionRequest + self, + *, + user_defined_listing_id: str, + request: CreateLibraryListingVersionRequest, ) -> LibraryListingVersion: """Creates a new library listing version""" return await self._do_json( @@ -4685,13 +5140,16 @@ async def post_library_listings_versions( method="POST", path_fmt="/v1/library_listings/{}/versions", path_args=[user_defined_listing_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) - async def post_llm_models(self, *, body: CreateLLMModelRequest) -> LLMModelHandle: + async def post_llm_models( + self, *, request: CreateLLMModelRequest + ) -> LLMModelHandle: """Creates a new BIS-LLM deployment""" return await self._do_json( LLMModelHandle, @@ -4699,14 +5157,15 @@ async def post_llm_models(self, *, body: CreateLLMModelRequest) -> LLMModelHandl method="POST", path_fmt="/v1/llm_models", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_llm_models_deployments( - self, *, model_id: str, body: CreateLLMModelVersionRequest + self, *, model_id: str, request: CreateLLMModelVersionRequest ) -> LLMModelHandle: """Creates a new BIS-LLM deployment version""" return await self._do_json( @@ -4715,14 +5174,15 @@ async def post_llm_models_deployments( method="POST", path_fmt="/v1/llm_models/{}/deployments", path_args=[model_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_loops_checkpoints_validate( - self, *, body: ValidateLoopsCheckpointRequest + self, *, request: ValidateLoopsCheckpointRequest ) -> ValidateLoopsCheckpointResponse: """Validates a Loops checkpoint bt:// URI""" return await self._do_json( @@ -4731,7 +5191,8 @@ async def post_loops_checkpoints_validate( method="POST", path_fmt="/v1/loops/checkpoints/validate", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -4748,13 +5209,14 @@ async def post_loops_deployments_deactivate( path_fmt="/v1/loops/deployments/{}/deactivate", path_args=[deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), ) async def post_loops_deployments_metrics( - self, *, deployment_id: str, body: GetLoopsDeploymentMetricsRequest + self, *, deployment_id: str, request: GetLoopsDeploymentMetricsRequest ) -> GetLoopsDeploymentMetricsResponse: """Gets metrics for a Loops trainer deployment""" return await self._do_json( @@ -4763,14 +5225,15 @@ async def post_loops_deployments_metrics( method="POST", path_fmt="/v1/loops/deployments/{}/metrics", path_args=[deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_loops_runs( - self, *, body: CreateLoopsRunRequest + self, *, request: CreateLoopsRunRequest ) -> CreateLoopsRunResponse: """Creates a Loops run""" return await self._do_json( @@ -4779,14 +5242,15 @@ async def post_loops_runs( method="POST", path_fmt="/v1/loops/runs", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_loops_samplers( - self, *, body: CreateLoopsSamplerRequest + self, *, request: CreateLoopsSamplerRequest ) -> CreateLoopsSamplerResponse: """Creates a Loops sampler""" return await self._do_json( @@ -4795,7 +5259,8 @@ async def post_loops_samplers( method="POST", path_fmt="/v1/loops/samplers", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -4810,13 +5275,14 @@ async def post_loops_sessions(self) -> CreateLoopsSessionResponse: path_fmt="/v1/loops/sessions", path_args=[], body=None, + query=None, success_code=200, error_codes=None, ), ) async def post_model_apis_snapshots( - self, *, body: CreateModelWeightSnapshotRequest + self, *, request: CreateModelWeightSnapshotRequest ) -> ModelWeightSnapshot: """Creates a model weight snapshot""" return await self._do_json( @@ -4825,14 +5291,15 @@ async def post_model_apis_snapshots( method="POST", path_fmt="/v1/model_apis/snapshots", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_model_apis_snapshots_model_id( - self, *, model_id: str, body: CreateModelWeightSnapshotRequest + self, *, model_id: str, request: CreateModelWeightSnapshotRequest ) -> ModelWeightSnapshot: """Creates a model weight snapshot""" return await self._do_json( @@ -4841,13 +5308,16 @@ async def post_model_apis_snapshots_model_id( method="POST", path_fmt="/v1/model_apis/snapshots/{}", path_args=[model_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) - async def post_models(self, *, body: CreateModelRequest) -> CreatedModelDeployment: + async def post_models( + self, *, request: CreateModelRequest + ) -> CreatedModelDeployment: """Creates a new model from a source""" return await self._do_json( CreatedModelDeployment, @@ -4855,14 +5325,15 @@ async def post_models(self, *, body: CreateModelRequest) -> CreatedModelDeployme method="POST", path_fmt="/v1/models", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_models_deployments( - self, *, model_id: str, body: CreateModelDeploymentRequest + self, *, model_id: str, request: CreateModelDeploymentRequest ) -> CreatedModelDeployment: """Adds a new deployment to a model""" return await self._do_json( @@ -4871,7 +5342,8 @@ async def post_models_deployments( method="POST", path_fmt="/v1/models/{}/deployments", path_args=[model_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -4888,6 +5360,7 @@ async def post_models_deployments_activate( path_fmt="/v1/models/{}/deployments/{}/activate", path_args=[model_id, deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -4904,6 +5377,7 @@ async def post_models_deployments_deactivate( path_fmt="/v1/models/{}/deployments/{}/deactivate", path_args=[model_id, deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -4920,6 +5394,7 @@ async def post_models_deployments_development_activate( path_fmt="/v1/models/{}/deployments/development/activate", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -4936,13 +5411,14 @@ async def post_models_deployments_development_deactivate( path_fmt="/v1/models/{}/deployments/development/deactivate", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), ) async def post_models_deployments_development_promote( - self, *, model_id: str, body: PromoteRequest + self, *, model_id: str, request: PromoteRequest ) -> Deployment: """Promotes a development deployment to production""" return await self._do_json( @@ -4951,7 +5427,8 @@ async def post_models_deployments_development_promote( method="POST", path_fmt="/v1/models/{}/deployments/development/promote", path_args=[model_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -4968,13 +5445,14 @@ async def post_models_deployments_development_retry( path_fmt="/v1/models/{}/deployments/development/retry", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), ) async def post_models_deployments_logs( - self, *, model_id: str, deployment_id: str, body: GetDeploymentLogsRequest + self, *, model_id: str, deployment_id: str, request: GetDeploymentLogsRequest ) -> GetLogsResponse: """Gets the logs for a model deployment (deprecated; use GET)""" return await self._do_json( @@ -4983,14 +5461,19 @@ async def post_models_deployments_logs( method="POST", path_fmt="/v1/models/{}/deployments/{}/logs", path_args=[model_id, deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_models_deployments_patches( - self, *, model_id: str, deployment_id: str, body: CreateDeploymentPatchRequest + self, + *, + model_id: str, + deployment_id: str, + request: CreateDeploymentPatchRequest, ) -> CreateDeploymentPatchResponse: """Stages a patch against a development deployment""" return await self._do_json( @@ -4999,14 +5482,19 @@ async def post_models_deployments_patches( method="POST", path_fmt="/v1/models/{}/deployments/{}/patches", path_args=[model_id, deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_models_deployments_patches_sync( - self, *, model_id: str, deployment_id: str, body: SyncDeploymentPatchesRequest + self, + *, + model_id: str, + deployment_id: str, + request: SyncDeploymentPatchesRequest, ) -> SyncDeploymentPatchesResponse: """Syncs staged patches to a development deployment""" return await self._do_json( @@ -5015,7 +5503,8 @@ async def post_models_deployments_patches_sync( method="POST", path_fmt="/v1/models/{}/deployments/{}/patches/sync", path_args=[model_id, deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -5032,6 +5521,7 @@ async def post_models_deployments_production_activate( path_fmt="/v1/models/{}/deployments/production/activate", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -5048,6 +5538,7 @@ async def post_models_deployments_production_deactivate( path_fmt="/v1/models/{}/deployments/production/deactivate", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -5064,13 +5555,14 @@ async def post_models_deployments_production_retry( path_fmt="/v1/models/{}/deployments/production/retry", path_args=[model_id], body=None, + query=None, success_code=200, error_codes=None, ), ) async def post_models_deployments_promote( - self, *, model_id: str, deployment_id: str, body: PromoteRequest + self, *, model_id: str, deployment_id: str, request: PromoteRequest ) -> Deployment: """Promotes a deployment to production""" return await self._do_json( @@ -5079,7 +5571,8 @@ async def post_models_deployments_promote( method="POST", path_fmt="/v1/models/{}/deployments/{}/promote", path_args=[model_id, deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -5096,13 +5589,14 @@ async def post_models_deployments_retry( path_fmt="/v1/models/{}/deployments/{}/retry", path_args=[model_id, deployment_id], body=None, + query=None, success_code=200, error_codes=None, ), ) async def post_models_deployments_ssh_sign( - self, *, model_id: str, deployment_id: str, body: SignSSHCertificateRequest + self, *, model_id: str, deployment_id: str, request: SignSSHCertificateRequest ) -> SignSSHCertificateResponse: """Signs an SSH certificate for an inference model""" return await self._do_json( @@ -5111,14 +5605,15 @@ async def post_models_deployments_ssh_sign( method="POST", path_fmt="/v1/models/{}/deployments/{}/ssh/sign", path_args=[model_id, deployment_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_models_environments( - self, *, model_id: str, body: CreateEnvironmentRequest + self, *, model_id: str, request: CreateEnvironmentRequest ) -> Environment: """Creates an environment""" return await self._do_json( @@ -5127,7 +5622,8 @@ async def post_models_environments( method="POST", path_fmt="/v1/models/{}/environments", path_args=[model_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -5144,6 +5640,7 @@ async def post_models_environments_activate( path_fmt="/v1/models/{}/environments/{}/activate", path_args=[model_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -5160,6 +5657,7 @@ async def post_models_environments_cancel_promotion( path_fmt="/v1/models/{}/environments/{}/cancel_promotion", path_args=[model_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -5176,6 +5674,7 @@ async def post_models_environments_deactivate( path_fmt="/v1/models/{}/environments/{}/deactivate", path_args=[model_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -5192,6 +5691,7 @@ async def post_models_environments_force_cancel_promotion( path_fmt="/v1/models/{}/environments/{}/force_cancel_promotion", path_args=[model_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -5208,6 +5708,7 @@ async def post_models_environments_force_roll_forward_promotion( path_fmt="/v1/models/{}/environments/{}/force_roll_forward_promotion", path_args=[model_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), @@ -5224,13 +5725,14 @@ async def post_models_environments_pause_promotion( path_fmt="/v1/models/{}/environments/{}/pause_promotion", path_args=[model_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), ) async def post_models_environments_promote( - self, *, model_id: str, env_name: str, body: PromoteToEnvironmentRequest + self, *, model_id: str, env_name: str, request: PromoteToEnvironmentRequest ) -> Deployment: """Promotes a deployment to an environment""" return await self._do_json( @@ -5239,7 +5741,8 @@ async def post_models_environments_promote( method="POST", path_fmt="/v1/models/{}/environments/{}/promote", path_args=[model_id, env_name], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -5256,13 +5759,14 @@ async def post_models_environments_resume_promotion( path_fmt="/v1/models/{}/environments/{}/resume_promotion", path_args=[model_id, env_name], body=None, + query=None, success_code=200, error_codes=None, ), ) async def post_prepare_model_upload( - self, *, body: PrepareModelUploadRequest + self, *, request: PrepareModelUploadRequest ) -> PrepareModelUploadResponse: """Validates a model push payload and issues upload credentials""" return await self._do_json( @@ -5271,13 +5775,14 @@ async def post_prepare_model_upload( method="POST", path_fmt="/v1/prepare_model_upload", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) - async def post_secrets(self, *, body: UpsertSecretRequest) -> Secret: + async def post_secrets(self, *, request: UpsertSecretRequest) -> Secret: """Upserts a secret""" return await self._do_json( Secret, @@ -5285,14 +5790,15 @@ async def post_secrets(self, *, body: UpsertSecretRequest) -> Secret: method="POST", path_fmt="/v1/secrets", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_teams_api_keys( - self, *, team_id: str, body: CreateAPIKeyRequest + self, *, team_id: str, request: CreateAPIKeyRequest ) -> APIKey: """Creates a team API key""" return await self._do_json( @@ -5301,14 +5807,15 @@ async def post_teams_api_keys( method="POST", path_fmt="/v1/teams/{}/api_keys", path_args=[team_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_teams_llm_models( - self, *, team_id: str, body: CreateLLMModelRequest + self, *, team_id: str, request: CreateLLMModelRequest ) -> LLMModelHandle: """Creates a new BIS-LLM deployment""" return await self._do_json( @@ -5317,14 +5824,15 @@ async def post_teams_llm_models( method="POST", path_fmt="/v1/teams/{}/llm_models", path_args=[team_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_teams_models( - self, *, team_id: str, body: CreateModelRequest + self, *, team_id: str, request: CreateModelRequest ) -> CreatedModelDeployment: """Creates a new model from a source""" return await self._do_json( @@ -5333,14 +5841,15 @@ async def post_teams_models( method="POST", path_fmt="/v1/teams/{}/models", path_args=[team_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_teams_secrets( - self, *, team_id: str, body: UpsertSecretRequest + self, *, team_id: str, request: UpsertSecretRequest ) -> Secret: """Upserts a secret in a team""" return await self._do_json( @@ -5349,14 +5858,15 @@ async def post_teams_secrets( method="POST", path_fmt="/v1/teams/{}/secrets", path_args=[team_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_teams_training_projects( - self, *, team_id: str, body: UpsertTrainingProjectRequest + self, *, team_id: str, request: UpsertTrainingProjectRequest ) -> UpsertTrainingProjectResponse: """Upserts a training project in a specific team""" return await self._do_json( @@ -5365,14 +5875,15 @@ async def post_teams_training_projects( method="POST", path_fmt="/v1/teams/{}/training_projects", path_args=[team_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_training_jobs_search( - self, *, body: SearchTrainingJobsRequest + self, *, request: SearchTrainingJobsRequest ) -> SearchTrainingJobsResponse: """Searches training jobs""" return await self._do_json( @@ -5381,14 +5892,15 @@ async def post_training_jobs_search( method="POST", path_fmt="/v1/training_jobs/search", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_training_projects( - self, *, body: UpsertTrainingProjectRequest + self, *, request: UpsertTrainingProjectRequest ) -> UpsertTrainingProjectResponse: """Upserts a training project""" return await self._do_json( @@ -5397,14 +5909,15 @@ async def post_training_projects( method="POST", path_fmt="/v1/training_projects", path_args=[], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), ) async def post_training_projects_jobs( - self, *, training_project_id: str, body: CreateTrainingJobRequest + self, *, training_project_id: str, request: CreateTrainingJobRequest ) -> CreateTrainingJobResponse: """Creates a training job""" return await self._do_json( @@ -5413,7 +5926,8 @@ async def post_training_projects_jobs( method="POST", path_fmt="/v1/training_projects/{}/jobs", path_args=[training_project_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -5424,7 +5938,7 @@ async def post_training_projects_jobs_logs( *, training_project_id: str, training_job_id: str, - body: GetTrainingJobLogsRequest, + request: GetTrainingJobLogsRequest, ) -> GetLogsResponse: """Gets the logs for a training job (deprecated; use GET)""" return await self._do_json( @@ -5433,7 +5947,8 @@ async def post_training_projects_jobs_logs( method="POST", path_fmt="/v1/training_projects/{}/jobs/{}/logs", path_args=[training_project_id, training_job_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -5444,7 +5959,7 @@ async def post_training_projects_jobs_metrics( *, training_project_id: str, training_job_id: str, - body: GetTrainingJobMetricsRequest, + request: GetTrainingJobMetricsRequest, ) -> GetTrainingJobMetricsResponse: """Gets the metrics for a training job (deprecated; use GET)""" return await self._do_json( @@ -5453,7 +5968,8 @@ async def post_training_projects_jobs_metrics( method="POST", path_fmt="/v1/training_projects/{}/jobs/{}/metrics", path_args=[training_project_id, training_job_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -5470,6 +5986,7 @@ async def post_training_projects_jobs_recreate( path_fmt="/v1/training_projects/{}/jobs/{}/recreate", path_args=[training_project_id, training_job_id], body=None, + query=None, success_code=200, error_codes=None, ), @@ -5480,7 +5997,7 @@ async def post_training_projects_jobs_ssh_sign( *, training_project_id: str, training_job_id: str, - body: SignSSHCertificateRequest, + request: SignSSHCertificateRequest, ) -> SignSSHCertificateResponse: """Signs an SSH certificate for a training job""" return await self._do_json( @@ -5489,7 +6006,8 @@ async def post_training_projects_jobs_ssh_sign( method="POST", path_fmt="/v1/training_projects/{}/jobs/{}/ssh/sign", path_args=[training_project_id, training_job_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -5500,7 +6018,7 @@ async def post_training_projects_jobs_stop( *, training_project_id: str, training_job_id: str, - body: StopTrainingJobRequest, + request: StopTrainingJobRequest, ) -> StopTrainingJobResponse: """Stops a training job""" return await self._do_json( @@ -5509,7 +6027,8 @@ async def post_training_projects_jobs_stop( method="POST", path_fmt="/v1/training_projects/{}/jobs/{}/stop", path_args=[training_project_id, training_job_id], - body=body, + body=request, + query=None, success_code=200, error_codes=None, ), @@ -5522,10 +6041,25 @@ async def _do(self, request: _ApiRequest) -> httpx.Response: json_body = None if request.body is not None: if isinstance(request.body, BaseModel): - json_body = request.body.model_dump(mode="json") + # Only fields the caller set are sent, so unset fields fall + # back to the server default rather than being reset here. + # An explicit None is kept, since null can mean "clear". + json_body = request.body.model_dump(mode="json", exclude_unset=True) else: json_body = request.body - response = await self._http_client.request(request.method, path, json=json_body) + params = None + if request.query is not None: + if isinstance(request.query, BaseModel): + # As above, plus dropping None: a null query parameter is + # meaningless and would otherwise serialize as an empty string. + params = request.query.model_dump( + mode="json", exclude_unset=True, exclude_none=True + ) + else: + params = request.query + response = await self._http_client.request( + request.method, path, json=json_body, params=params + ) if response.status_code != request.success_code: raise ResponseError(status_code=response.status_code, body=response.text) return response diff --git a/baseten/client/managementapi/_models.py b/baseten/client/managementapi/_models.py index 0950e23..fc62e3a 100644 --- a/baseten/client/managementapi/_models.py +++ b/baseten/client/managementapi/_models.py @@ -280,6 +280,263 @@ class GatewayProvider(Enum): OPENAI_COMPATIBLE = "OPENAI_COMPATIBLE" +class GetTeamsRequest(BaseModel): + name: Annotated[ + str | None, + Field( + description="When set, returns only the team with this exact name, if any.", + title="Name", + ), + ] = None + + +class GetModelsRequest(BaseModel): + name: Annotated[ + str | None, + Field( + description="When set, returns only models with this exact name, if any. On a team-scoped route this matches at most one model; on the org-wide route it may match models in multiple teams, since names are unique only within a team.", + title="Name", + ), + ] = None + + +class GetTeamsModelsRequest(BaseModel): + name: Annotated[ + str | None, + Field( + description="When set, returns only models with this exact name, if any. On a team-scoped route this matches at most one model; on the org-wide route it may match models in multiple teams, since names are unique only within a team.", + title="Name", + ), + ] = None + + +class GetModelsDeploymentsRequest(BaseModel): + name: Annotated[ + str | None, + Field( + description="When set, returns only the deployment with this exact name, if any.", + title="Name", + ), + ] = None + + +class GetModelsDeploymentsConfigRequest(BaseModel): + output_format: Annotated[ + DeploymentConfigOutputFormat | None, + Field( + description="'raw': verbatim config.yaml with comments (not available for deployments created before 2026-04-30). 'parsed': dict with server-side defaults applied (always available). 'both': both fields populated." + ), + ] = DeploymentConfigOutputFormat.both + + +class Limit(RootModel[int]): + root: Annotated[ + int, + Field( + description="Limit of logs to fetch in a single request", + ge=1, + le=1000, + title="Limit", + ), + ] = 500 + + +class Replica(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="Only return logs emitted by this replica (5-char short ID).", + max_length=256, + title="Replica", + ), + ] = None + + +class RequestId(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="Only return logs tagged with this inference request ID.", + max_length=256, + title="Request Id", + ), + ] = None + + +class Component(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="Only return logs from this component.", + max_length=256, + title="Component", + ), + ] = None + + +class SearchPattern(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", + max_length=256, + title="Search Pattern", + ), + ] = None + + +class GetTrainingProjectsJobsMetricsRequest(BaseModel): + end_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch millis timestamp to end fetching metrics", + title="End Epoch Millis", + ), + ] = None + start_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch millis timestamp to start fetching metrics.", + title="Start Epoch Millis", + ), + ] = None + step_seconds: Annotated[ + int | None, + Field( + description="Resolution of the returned series, in seconds. When omitted, a step is derived from the time range so large windows return fewer points.", + title="Step Seconds", + ), + ] = None + + +class GetTrainingProjectsJobsCheckpointFilesRequest(BaseModel): + page_size: Annotated[ + int | None, + Field( + description="Max files per page (default 1000).", ge=1, title="Page Size" + ), + ] = 1000 + page_token: Annotated[ + int | None, + Field( + description="Offset into the file list (default 0).", + ge=0, + title="Page Token", + ), + ] = 0 + + +class GetLoopsRunsRequest(BaseModel): + run_id: Annotated[ + str | None, + Field(description="Filter by run ID.", examples=["k4q95w5"], title="Run Id"), + ] = None + base_model: Annotated[ + str | None, + Field( + description="Filter runs by base model name.", + examples=["Qwen/Qwen3-8B"], + title="Base Model", + ), + ] = None + + +class GetLoopsCheckpointsRequest(BaseModel): + run_id: Annotated[ + str | None, + Field( + description="Filter by run ID. Returns all checkpoints saved by the run.", + examples=["k4q95w5"], + title="Run Id", + ), + ] = None + base_model: Annotated[ + str | None, + Field( + description="Filter by base model. Returns checkpoints across the caller's runs of this base model.", + examples=["Qwen/Qwen3-8B"], + title="Base Model", + ), + ] = None + checkpoint_path: Annotated[ + str | None, + Field( + description="bt:// URI of a Loops checkpoint. Form: bt://loops:/(weights|sampler_weights)/.", + examples=["bt://loops:k4q95w5/sampler_weights/step-100"], + title="Checkpoint Path", + ), + ] = None + + +class GetModelApisRequest(BaseModel): + cursor: Annotated[ + str | None, + Field( + description="Opaque cursor returned by a previous page. Omit to fetch the first page.", + title="Cursor", + ), + ] = None + limit: Annotated[ + int | None, + Field( + description="Maximum number of items to return.", + ge=1, + le=1000, + title="Limit", + ), + ] = 100 + added_only: Annotated[ + bool | None, + Field( + description="When true, restrict the result to Model APIs the workspace has added. Defaults to the full visible catalog.", + title="Added Only", + ), + ] = False + + +class GetBillingUsageSummaryRequest(BaseModel): + start_date: Annotated[ + AwareDatetime, + Field( + description="Start date (ISO 8601, UTC). Earliest queryable: 2026-01-01.", + title="Start Date", + ), + ] + end_date: Annotated[ + AwareDatetime, + Field( + description="End date in ISO 8601 format (UTC). Date range cannot exceed 31 days.", + title="End Date", + ), + ] + + +class GetUsersRequest(BaseModel): + cursor: Annotated[ + str | None, + Field( + description="Opaque cursor returned by a previous page. Omit to fetch the first page.", + title="Cursor", + ), + ] = None + limit: Annotated[ + int | None, + Field( + description="Maximum number of items to return.", + ge=1, + le=1000, + title="Limit", + ), + ] = 100 + email: Annotated[ + str | None, + Field( + description="When set, returns only users with this exact email, if any.", + title="Email", + ), + ] = None + + class Secret(BaseModel): id: Annotated[ str, @@ -1224,65 +1481,9 @@ class SortOrder(Enum): desc = "desc" -class Limit(RootModel[int]): - root: Annotated[ - int, - Field( - description="Limit of logs to fetch in a single request", - ge=1, - le=1000, - title="Limit", - ), - ] = 500 - - -class Replica(RootModel[str]): - root: Annotated[ - str | None, - Field( - description="Only return logs emitted by this replica (5-char short ID).", - max_length=256, - title="Replica", - ), - ] = None - - -class RequestId(RootModel[str]): - root: Annotated[ - str | None, - Field( - description="Only return logs tagged with this inference request ID.", - max_length=256, - title="Request Id", - ), - ] = None - - -class Component(RootModel[str]): - root: Annotated[ - str | None, - Field( - description="Only return logs from this component.", - max_length=256, - title="Component", - ), - ] = None - - -class SearchPattern(RootModel[str]): - root: Annotated[ - str | None, - Field( - description="RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", - max_length=256, - title="Search Pattern", - ), - ] = None - - -class GetDeploymentLogsRequest(BaseModel): - start_epoch_millis: Annotated[ - int | None, +class GetDeploymentLogsRequest(BaseModel): + start_epoch_millis: Annotated[ + int | None, Field( description="Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", title="Start Epoch Millis", @@ -5132,6 +5333,359 @@ class LoadCheckpointConfig(BaseModel): ] = None +class GetModelsDeploymentsLogsRequest(BaseModel): + start_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + title="Start Epoch Millis", + ), + ] = None + end_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + title="End Epoch Millis", + ), + ] = None + direction: Annotated[SortOrder | None, Field(description="Sort order for logs")] = ( + None + ) + limit: Annotated[ + Limit | None, + Field( + default_factory=lambda: Limit(500), + description="Limit of logs to fetch in a single request", + title="Limit", + ), + ] + min_level: Annotated[ + LogLevel | None, + Field( + description="Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." + ), + ] = None + replica: Annotated[ + Replica | None, + Field( + description="Only return logs emitted by this replica (5-char short ID).", + title="Replica", + ), + ] = None + request_id: Annotated[ + RequestId | None, + Field( + description="Only return logs tagged with this inference request ID.", + title="Request Id", + ), + ] = None + component: Annotated[ + Component | None, + Field(description="Only return logs from this component.", title="Component"), + ] = None + search_pattern: Annotated[ + SearchPattern | None, + Field( + description="RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", + title="Search Pattern", + ), + ] = None + includes: Annotated[ + list[str] | None, + Field( + description="Case-sensitive substrings that must all appear in the log message.", + max_length=8, + title="Includes", + ), + ] = None + excludes: Annotated[ + list[str] | None, + Field( + description="Case-sensitive substrings; lines containing any of these are dropped.", + max_length=8, + title="Excludes", + ), + ] = None + + +class GetModelsDeploymentsMetricsRequest(BaseModel): + mode: Annotated[ + ModelMetricMode | None, + Field( + description="'CURRENT': a single instantaneous snapshot at now; start/end must be omitted. 'SUMMARY': a single value set aggregating the whole window. 'SERIES': evenly-spaced value sets across the window, with the step derived from the window duration." + ), + ] = ModelMetricMode.CURRENT + start_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch millis timestamp to start fetching metrics. Defaults to one hour before the end.", + title="Start Epoch Millis", + ), + ] = None + end_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch millis timestamp to end fetching metrics. Defaults to the current time. The window between start and end must not exceed 7 days.", + title="End Epoch Millis", + ), + ] = None + metrics: Annotated[ + list[str] | None, + Field( + description="Names of the metrics to return; see https://docs.baseten.co/observability/export-metrics/supported-metrics for the available names. When omitted, a default set is returned: baseten_replicas_active, baseten_inference_requests_total, and baseten_end_to_end_response_time_seconds. Unknown names are rejected; valid names that do not apply are omitted from the response.", + title="Metrics", + ), + ] = None + + +class GetModelsEnvironmentsLogsRequest(BaseModel): + start_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + title="Start Epoch Millis", + ), + ] = None + end_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + title="End Epoch Millis", + ), + ] = None + direction: Annotated[SortOrder | None, Field(description="Sort order for logs")] = ( + None + ) + limit: Annotated[ + Limit | None, + Field( + default_factory=lambda: Limit(500), + description="Limit of logs to fetch in a single request", + title="Limit", + ), + ] + min_level: Annotated[ + LogLevel | None, + Field( + description="Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." + ), + ] = None + replica: Annotated[ + Replica | None, + Field( + description="Only return logs emitted by this replica (5-char short ID).", + title="Replica", + ), + ] = None + request_id: Annotated[ + RequestId | None, + Field( + description="Only return logs tagged with this inference request ID.", + title="Request Id", + ), + ] = None + component: Annotated[ + Component | None, + Field(description="Only return logs from this component.", title="Component"), + ] = None + search_pattern: Annotated[ + SearchPattern | None, + Field( + description="RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", + title="Search Pattern", + ), + ] = None + includes: Annotated[ + list[str] | None, + Field( + description="Case-sensitive substrings that must all appear in the log message.", + max_length=8, + title="Includes", + ), + ] = None + excludes: Annotated[ + list[str] | None, + Field( + description="Case-sensitive substrings; lines containing any of these are dropped.", + max_length=8, + title="Excludes", + ), + ] = None + + +class GetModelsEnvironmentsMetricsRequest(BaseModel): + mode: Annotated[ + ModelMetricMode | None, + Field( + description="'CURRENT': a single instantaneous snapshot at now; start/end must be omitted. 'SUMMARY': a single value set aggregating the whole window. 'SERIES': evenly-spaced value sets across the window, with the step derived from the window duration." + ), + ] = ModelMetricMode.CURRENT + start_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch millis timestamp to start fetching metrics. Defaults to one hour before the end.", + title="Start Epoch Millis", + ), + ] = None + end_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch millis timestamp to end fetching metrics. Defaults to the current time. The window between start and end must not exceed 7 days.", + title="End Epoch Millis", + ), + ] = None + metrics: Annotated[ + list[str] | None, + Field( + description="Names of the metrics to return; see https://docs.baseten.co/observability/export-metrics/supported-metrics for the available names. When omitted, a default set is returned: baseten_replicas_active, baseten_inference_requests_total, and baseten_end_to_end_response_time_seconds. Unknown names are rejected; valid names that do not apply are omitted from the response.", + title="Metrics", + ), + ] = None + + +class GetChainsDeploymentsChainletsLogsRequest(BaseModel): + start_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + title="Start Epoch Millis", + ), + ] = None + end_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + title="End Epoch Millis", + ), + ] = None + direction: Annotated[SortOrder | None, Field(description="Sort order for logs")] = ( + None + ) + limit: Annotated[ + Limit | None, + Field( + default_factory=lambda: Limit(500), + description="Limit of logs to fetch in a single request", + title="Limit", + ), + ] + min_level: Annotated[ + LogLevel | None, + Field( + description="Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." + ), + ] = None + replica: Annotated[ + Replica | None, + Field( + description="Only return logs emitted by this replica (5-char short ID).", + title="Replica", + ), + ] = None + request_id: Annotated[ + RequestId | None, + Field( + description="Only return logs tagged with this inference request ID.", + title="Request Id", + ), + ] = None + component: Annotated[ + Component | None, + Field(description="Only return logs from this component.", title="Component"), + ] = None + search_pattern: Annotated[ + SearchPattern | None, + Field( + description="RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", + title="Search Pattern", + ), + ] = None + includes: Annotated[ + list[str] | None, + Field( + description="Case-sensitive substrings that must all appear in the log message.", + max_length=8, + title="Includes", + ), + ] = None + excludes: Annotated[ + list[str] | None, + Field( + description="Case-sensitive substrings; lines containing any of these are dropped.", + max_length=8, + title="Excludes", + ), + ] = None + + +class GetTrainingProjectsJobsLogsRequest(BaseModel): + start_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + title="Start Epoch Millis", + ), + ] = None + end_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + title="End Epoch Millis", + ), + ] = None + direction: Annotated[SortOrder | None, Field(description="Sort order for logs")] = ( + None + ) + limit: Annotated[ + Limit | None, + Field( + default_factory=lambda: Limit(500), + description="Limit of logs to fetch in a single request", + title="Limit", + ), + ] + min_level: Annotated[ + LogLevel | None, + Field( + description="Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." + ), + ] = None + + +class GetLoopsDeploymentsLogsRequest(BaseModel): + start_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + title="Start Epoch Millis", + ), + ] = None + end_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + title="End Epoch Millis", + ), + ] = None + direction: Annotated[SortOrder | None, Field(description="Sort order for logs")] = ( + None + ) + limit: Annotated[ + Limit | None, + Field( + default_factory=lambda: Limit(500), + description="Limit of logs to fetch in a single request", + title="Limit", + ), + ] + min_level: Annotated[ + LogLevel | None, + Field( + description="Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." + ), + ] = None + + class EnvironmentGroupManageAccess(BaseModel): is_restricted: Annotated[ bool, diff --git a/pyproject.toml b/pyproject.toml index 95185b9..0f6fba2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "baseten" -version = "0.9.1" +version = "0.10.0" description = "Baseten Python SDK" readme = "README.md" license = "MIT" diff --git a/scripts/apigen/clientgen.py b/scripts/apigen/clientgen.py index d08b99d..3ed67ae 100644 --- a/scripts/apigen/clientgen.py +++ b/scripts/apigen/clientgen.py @@ -26,12 +26,19 @@ class _Operation: success_code: int error_codes: dict[int, str] | None summary: str + query_ref: str + query_required: bool -def _extract_operations(spec: dict) -> list[_Operation]: - paths = spec.get("paths", {}) +def resolve_method_names(spec: dict) -> dict[tuple[str, str], str]: + """Map each (path, http_method) to its resolved client method name. - # Collect raw operation data with short names (all params stripped). + Names are derived from the method and path, using a trailing path + parameter only where needed to disambiguate collisions. Shared with + preprocessing so injected query-parameter schemas can be named to + match their operation's method. + """ + paths = spec.get("paths", {}) raw: list[tuple[str, str, dict]] = [] short_names: dict[str, int] = {} for path, path_item in paths.items(): @@ -44,8 +51,7 @@ def _extract_operations(spec: dict) -> list[_Operation]: ) short_names[name] = short_names.get(name, 0) + 1 - # Build operations, using trailing param only where needed to disambiguate. - ops: list[_Operation] = [] + result: dict[tuple[str, str], str] = {} for path, http_method, op_data in raw: short = _derive_method_name( http_method, path, op_data, keep_trailing_param=False @@ -56,20 +62,52 @@ def _extract_operations(spec: dict) -> list[_Operation]: ) else: name = short - ops.append( - _Operation( - name=name, - http_method=http_method.upper(), - path=path, - path_params=_PATH_PARAM_RE.findall(path), - has_body="requestBody" in op_data, - req_body_ref=_body_schema_ref(spec, op_data), - resp_ref=_response_schema_ref(spec, op_data), - success_code=_extract_success_code(op_data, http_method, path), - error_codes=_error_code_map(spec, op_data), - summary=op_data.get("summary", ""), + result[(path, http_method)] = name + return result + + +def query_request_model_name(method_name: str) -> str: + """Model name for an operation's injected query-parameter schema.""" + return _snake_to_pascal(method_name) + "Request" + + +def _snake_to_pascal(s: str) -> str: + return "".join(part.capitalize() for part in s.split("_")) + + +def _extract_operations(spec: dict) -> list[_Operation]: + paths = spec.get("paths", {}) + names = resolve_method_names(spec) + + ops: list[_Operation] = [] + for path, path_item in paths.items(): + for http_method, op_data in path_item.items(): + if http_method == "parameters" or not isinstance(op_data, dict): + continue + name = names[(path, http_method)] + query_params = [ + p + for p in op_data.get("parameters", []) + if isinstance(p, dict) and p.get("in") == "query" + ] + query_ref = query_request_model_name(name) if query_params else "" + query_required = any(p.get("required") for p in query_params) + ops.append( + _Operation( + name=name, + http_method=http_method.upper(), + path=path, + path_params=_PATH_PARAM_RE.findall(path), + has_body="requestBody" in op_data, + req_body_ref=_body_schema_ref(spec, op_data), + resp_ref=_response_schema_ref(spec, op_data), + success_code=_extract_success_code(op_data, http_method, path), + error_codes=_error_code_map(spec, op_data), + summary=op_data.get("summary", ""), + query_ref=query_ref, + query_required=query_required, + ) ) - ) ops.sort(key=lambda o: o.name) return ops @@ -189,6 +227,8 @@ def _render_client(ops: list[_Operation]) -> str: for op in ops: if op.req_body_ref: model_imports.add(op.req_body_ref) + if op.query_ref: + model_imports.add(op.query_ref) if op.resp_ref: model_imports.add(op.resp_ref) for ref in (op.error_codes or {}).values(): @@ -255,6 +295,7 @@ class _ApiRequest: path_fmt: str path_args: list[str] body: Any + query: Any success_code: int error_codes: dict[int, str] | None """ @@ -325,10 +366,23 @@ def __init__(self, http_client: {http_cls}) -> None: json_body = None if request.body is not None: if isinstance(request.body, BaseModel): - json_body = request.body.model_dump(mode="json") + # Only fields the caller set are sent, so unset fields fall + # back to the server default rather than being reset here. + # An explicit None is kept, since null can mean "clear". + json_body = request.body.model_dump(mode="json", exclude_unset=True) else: json_body = request.body - response = {aw}self._http_client.request(request.method, path, json=json_body) + params = None + if request.query is not None: + if isinstance(request.query, BaseModel): + # As above, plus dropping None: a null query parameter is + # meaningless and would otherwise serialize as an empty string. + params = request.query.model_dump( + mode="json", exclude_unset=True, exclude_none=True + ) + else: + params = request.query + response = {aw}self._http_client.request(request.method, path, json=json_body, params=params) if response.status_code != request.success_code: {error_dispatch}\ raise ResponseError(status_code=response.status_code, body=response.text) @@ -358,18 +412,36 @@ def _render_method(op: _Operation, *, is_async: bool) -> str: adef = "async def" if is_async else "def" aw = "await " if is_async else "" + # An operation carries at most one input model: a request body (any + # method other than GET) or query parameters (GET only). Both surface + # as a single keyword-only `request` argument. Query requests with no + # required fields are optional so callers can omit them entirely; body + # requests are always required so an empty body still sends `{}`. + if op.query_ref: + input_type = op.query_ref + input_required = op.query_required + elif op.has_body: + input_type = op.req_body_ref if op.req_body_ref else "Any" + input_required = True + else: + input_type = "" + input_required = False + params = ["self"] - if op.path_params or op.has_body: + if op.path_params or input_type: params.append("*") for p in op.path_params: params.append(f"{p}: str") - if op.has_body: - body_type = op.req_body_ref if op.req_body_ref else "Any" - params.append(f"body: {body_type}") + if input_type: + if input_required: + params.append(f"request: {input_type}") + else: + params.append(f"request: {input_type} | None = None") ret = f" -> {op.resp_ref}" if op.resp_ref else " -> None" path_args = f"[{', '.join(op.path_params)}]" if op.path_params else "[]" - body_arg = "body" if op.has_body else "None" + body_arg = "request" if (input_type and not op.query_ref) else "None" + query_arg = "request" if op.query_ref else "None" if op.error_codes: codes = sorted(op.error_codes.items()) @@ -383,6 +455,7 @@ def _render_method(op: _Operation, *, is_async: bool) -> str: f"path_fmt={_path_fmt(op.path)!r}, " f"path_args={path_args}, " f"body={body_arg}, " + f"query={query_arg}, " f"success_code={op.success_code}, " f"error_codes={error_expr})" ) diff --git a/scripts/apigen/preprocess.py b/scripts/apigen/preprocess.py index c4f0518..4d666c7 100644 --- a/scripts/apigen/preprocess.py +++ b/scripts/apigen/preprocess.py @@ -1,8 +1,11 @@ """Preprocesses OpenAPI specs for code generation.""" +import copy import json import re +from scripts.apigen.clientgen import query_request_model_name, resolve_method_names + def preprocess_truss_config_schema(data: bytes) -> bytes: doc = json.loads(data) @@ -56,6 +59,13 @@ def preprocess_spec(data: bytes) -> bytes: # wrapper classes. _hoist_component_schemas(doc) + # Synthesize a request schema per GET operation's query parameters so + # datamodel-code-generator emits a typed model for them (it only + # generates query-parameter models under the paths scope, which drags + # in unwanted per-operation wrappers). Injected before the V1 rename + # below so their $refs to enums are rewritten with everything else. + _inject_query_request_schemas(doc) + # datamodel-code-generator generates empty BaseModel classes for # schemas that are bare type: object with no properties (e.g. # PredictInput). Adding additionalProperties makes it correctly @@ -98,6 +108,53 @@ def _hoist_component_schemas(doc: dict) -> None: content["schema"] = {"$ref": f"#/components/schemas/{name}"} +def _inject_query_request_schemas(doc: dict) -> None: + # Build an object schema whose properties are the operation's query + # parameters, named to match its client method (e.g. get_users -> + # GetUsersRequest). Each parameter's own schema (enum $refs, arrays, + # nullable wrappers, constraints) is reused verbatim so the third + # party types every field. GET carries only query params and every + # other method only a body, so this name never collides with a body. + schemas = doc.setdefault("components", {}).setdefault("schemas", {}) + method_names = resolve_method_names(doc) + + for path, path_item in doc.get("paths", {}).items(): + for http_method, op in path_item.items(): + if http_method == "parameters" or not isinstance(op, dict): + continue + query_params = [ + p + for p in op.get("parameters", []) + if isinstance(p, dict) and p.get("in") == "query" + ] + if not query_params: + continue + if "requestBody" in op: + raise ValueError( + f"{http_method.upper()} {path} has both a request body and " + "query parameters; the client generator assumes GET carries " + "only query parameters and other methods only a body" + ) + name = query_request_model_name(method_names[(path, http_method)]) + if name in schemas: + raise ValueError( + f"injected query schema {name} collides with an existing schema" + ) + properties: dict = {} + required: list[str] = [] + for p in query_params: + schema = copy.deepcopy(p.get("schema", {})) + if "description" not in schema and p.get("description"): + schema["description"] = p["description"] + properties[p["name"]] = schema + if p.get("required"): + required.append(p["name"]) + obj: dict = {"type": "object", "title": name, "properties": properties} + if required: + obj["required"] = required + schemas[name] = obj + + def _fix_bare_object_schemas(doc: dict) -> None: schemas = doc.get("components", {}).get("schemas", {}) for schema in schemas.values(): diff --git a/tests/client/test_inference.py b/tests/client/test_inference.py index e729f54..598f3fe 100644 --- a/tests/client/test_inference.py +++ b/tests/client/test_inference.py @@ -26,7 +26,7 @@ def test_predict_production_sync() -> None: fake = FakeTransport(200, {"result": 42}) client = make_sync_client(fake) - resp = client.api.predict_production(body=PredictInput({"input": "hello"})) + resp = client.api.predict_production(request=PredictInput({"input": "hello"})) assert resp.root["result"] == 42 assert fake.capture.method == "POST" assert fake.capture.path == "/production/predict" @@ -41,7 +41,7 @@ async def test_predict_production() -> None: fake = FakeTransport(200, {"result": 42}) client = make_async_client(fake) - resp = await client.api.predict_production(body=PredictInput({"input": "hello"})) + resp = await client.api.predict_production(request=PredictInput({"input": "hello"})) assert resp.root["result"] == 42 assert fake.capture.method == "POST" assert fake.capture.path == "/production/predict" @@ -56,7 +56,7 @@ async def test_async_predict_201() -> None: client = make_async_client(fake) resp = await client.api.async_predict_production( - body=baseten.client.inferenceapi.AsyncPredictRequest( + request=baseten.client.inferenceapi.AsyncPredictRequest( model_input={"prompt": "test"}, ), ) @@ -72,7 +72,7 @@ async def test_typed_error() -> None: client = make_async_client(fake) with pytest.raises(baseten.client.inferenceapi.ResponseErrorResponse) as exc_info: - await client.api.predict_production(body=PredictInput({})) + await client.api.predict_production(request=PredictInput({})) assert exc_info.value.status_code == 429 assert exc_info.value.error_response.error == "rate limited" await client.close() @@ -84,7 +84,7 @@ async def test_unknown_status_falls_back_to_response_error() -> None: client = make_async_client(fake) with pytest.raises(baseten.client.inferenceapi.ResponseError) as exc_info: - await client.api.predict_production(body=PredictInput({})) + await client.api.predict_production(request=PredictInput({})) assert exc_info.value.status_code == 418 assert "teapot" in exc_info.value.body await client.close() diff --git a/tests/client/test_management.py b/tests/client/test_management.py index 63f1b8d..9aff422 100644 --- a/tests/client/test_management.py +++ b/tests/client/test_management.py @@ -79,6 +79,32 @@ async def test_get_models() -> None: await client.close() +def test_get_with_query_params() -> None: + fake = FakeTransport(200, {"items": [], "pagination": {"has_more": False}}) + client = make_sync_client(fake) + + client.api.get_model_apis( + request=baseten.client.managementapi.GetModelApisRequest(added_only=True) + ) + + path, _, query = fake.capture.path.partition("?") + assert path == "/v1/model_apis" + # The set field serializes, the bool as a lowercase literal. Fields the + # caller left unset are dropped so the server applies its own defaults, + # even `limit`, which has a non-None default on the model. + assert query == "added_only=true" + client.close() + + +def test_get_query_params_omitted_when_absent() -> None: + fake = FakeTransport(200, {"items": [], "pagination": {"has_more": False}}) + client = make_sync_client(fake) + + client.api.get_model_apis() + assert fake.capture.path == "/v1/model_apis" + client.close() + + @pytest.mark.asyncio async def test_path_params_escaped() -> None: fake = FakeTransport(200, MINIMAL_MODEL) @@ -95,7 +121,7 @@ async def test_post_with_body() -> None: client = make_async_client(fake) resp = await client.api.post_secrets( - body=baseten.client.managementapi.UpsertSecretRequest( + request=baseten.client.managementapi.UpsertSecretRequest( name="MY_SECRET", value="s3cret", ), diff --git a/tests/test_e2e.py b/tests/test_e2e.py index 6cee07f..8b32acc 100644 --- a/tests/test_e2e.py +++ b/tests/test_e2e.py @@ -131,7 +131,7 @@ async def test_get_model_async() -> None: async def test_inference() -> None: async with async_inference_client() as client: result = await client.api.predict_production( - body=baseten.client.inferenceapi.PredictInput({"prompt": "hello"}), + request=baseten.client.inferenceapi.PredictInput({"prompt": "hello"}), ) assert result.root is not None @@ -145,7 +145,7 @@ async def test_api_key_crud() -> None: async with async_management_client() as client: try: created = await client.api.post_api_keys( - body=baseten.client.managementapi.CreateAPIKeyRequest( + request=baseten.client.managementapi.CreateAPIKeyRequest( name=key_name, type=baseten.client.managementapi.APIKeyCategory.PERSONAL, ), diff --git a/uv.lock b/uv.lock index 6d556a4..6e3f6f1 100644 --- a/uv.lock +++ b/uv.lock @@ -96,7 +96,7 @@ wheels = [ [[package]] name = "baseten" -version = "0.9.1" +version = "0.10.0" source = { editable = "." } dependencies = [ { name = "httpx" },